chess2img 0.1.0 → 0.1.2
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/ATTRIBUTION.md +14 -3
- package/README.md +39 -16
- package/assets/themes/alpha/bB.png +0 -0
- package/assets/themes/alpha/bK.png +0 -0
- package/assets/themes/alpha/bN.png +0 -0
- package/assets/themes/alpha/bP.png +0 -0
- package/assets/themes/alpha/bQ.png +0 -0
- package/assets/themes/alpha/bR.png +0 -0
- package/assets/themes/alpha/wB.png +0 -0
- package/assets/themes/alpha/wK.png +0 -0
- package/assets/themes/alpha/wN.png +0 -0
- package/assets/themes/alpha/wP.png +0 -0
- package/assets/themes/alpha/wQ.png +0 -0
- package/assets/themes/alpha/wR.png +0 -0
- package/assets/themes/cburnett/bB.png +0 -0
- package/assets/themes/cburnett/bK.png +0 -0
- package/assets/themes/cburnett/bN.png +0 -0
- package/assets/themes/cburnett/bP.png +0 -0
- package/assets/themes/cburnett/bQ.png +0 -0
- package/assets/themes/cburnett/bR.png +0 -0
- package/assets/themes/cburnett/wB.png +0 -0
- package/assets/themes/cburnett/wK.png +0 -0
- package/assets/themes/cburnett/wN.png +0 -0
- package/assets/themes/cburnett/wP.png +0 -0
- package/assets/themes/cburnett/wQ.png +0 -0
- package/assets/themes/cburnett/wR.png +0 -0
- package/assets/themes/cheq/bB.png +0 -0
- package/assets/themes/cheq/bK.png +0 -0
- package/assets/themes/cheq/bN.png +0 -0
- package/assets/themes/cheq/bP.png +0 -0
- package/assets/themes/cheq/bQ.png +0 -0
- package/assets/themes/cheq/bR.png +0 -0
- package/assets/themes/cheq/wB.png +0 -0
- package/assets/themes/cheq/wK.png +0 -0
- package/assets/themes/cheq/wN.png +0 -0
- package/assets/themes/cheq/wP.png +0 -0
- package/assets/themes/cheq/wQ.png +0 -0
- package/assets/themes/cheq/wR.png +0 -0
- package/assets/themes/leipzig/bB.png +0 -0
- package/assets/themes/leipzig/bK.png +0 -0
- package/assets/themes/leipzig/bN.png +0 -0
- package/assets/themes/leipzig/bP.png +0 -0
- package/assets/themes/leipzig/bQ.png +0 -0
- package/assets/themes/leipzig/bR.png +0 -0
- package/assets/themes/leipzig/wB.png +0 -0
- package/assets/themes/leipzig/wK.png +0 -0
- package/assets/themes/leipzig/wN.png +0 -0
- package/assets/themes/leipzig/wP.png +0 -0
- package/assets/themes/leipzig/wQ.png +0 -0
- package/assets/themes/leipzig/wR.png +0 -0
- package/assets/themes/merida/bB.png +0 -0
- package/assets/themes/merida/bK.png +0 -0
- package/assets/themes/merida/bN.png +0 -0
- package/assets/themes/merida/bP.png +0 -0
- package/assets/themes/merida/bQ.png +0 -0
- package/assets/themes/merida/bR.png +0 -0
- package/assets/themes/merida/wB.png +0 -0
- package/assets/themes/merida/wK.png +0 -0
- package/assets/themes/merida/wN.png +0 -0
- package/assets/themes/merida/wP.png +0 -0
- package/assets/themes/merida/wQ.png +0 -0
- package/assets/themes/merida/wR.png +0 -0
- package/dist/index.cjs +43 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +43 -12
- package/dist/index.js.map +1 -1
- package/package.json +11 -1
- package/assets/themes/alpha/bB.svg +0 -20
- package/assets/themes/alpha/bK.svg +0 -21
- package/assets/themes/alpha/bN.svg +0 -19
- package/assets/themes/alpha/bP.svg +0 -19
- package/assets/themes/alpha/bQ.svg +0 -22
- package/assets/themes/alpha/bR.svg +0 -22
- package/assets/themes/alpha/wB.svg +0 -20
- package/assets/themes/alpha/wK.svg +0 -21
- package/assets/themes/alpha/wN.svg +0 -19
- package/assets/themes/alpha/wP.svg +0 -19
- package/assets/themes/alpha/wQ.svg +0 -22
- package/assets/themes/alpha/wR.svg +0 -22
- package/assets/themes/cburnett/bB.svg +0 -20
- package/assets/themes/cburnett/bK.svg +0 -21
- package/assets/themes/cburnett/bN.svg +0 -19
- package/assets/themes/cburnett/bP.svg +0 -19
- package/assets/themes/cburnett/bQ.svg +0 -22
- package/assets/themes/cburnett/bR.svg +0 -22
- package/assets/themes/cburnett/wB.svg +0 -20
- package/assets/themes/cburnett/wK.svg +0 -21
- package/assets/themes/cburnett/wN.svg +0 -19
- package/assets/themes/cburnett/wP.svg +0 -19
- package/assets/themes/cburnett/wQ.svg +0 -22
- package/assets/themes/cburnett/wR.svg +0 -22
- package/assets/themes/cheq/bB.svg +0 -20
- package/assets/themes/cheq/bK.svg +0 -21
- package/assets/themes/cheq/bN.svg +0 -19
- package/assets/themes/cheq/bP.svg +0 -19
- package/assets/themes/cheq/bQ.svg +0 -22
- package/assets/themes/cheq/bR.svg +0 -22
- package/assets/themes/cheq/wB.svg +0 -20
- package/assets/themes/cheq/wK.svg +0 -21
- package/assets/themes/cheq/wN.svg +0 -19
- package/assets/themes/cheq/wP.svg +0 -19
- package/assets/themes/cheq/wQ.svg +0 -22
- package/assets/themes/cheq/wR.svg +0 -22
- package/assets/themes/leipzig/bB.svg +0 -20
- package/assets/themes/leipzig/bK.svg +0 -21
- package/assets/themes/leipzig/bN.svg +0 -19
- package/assets/themes/leipzig/bP.svg +0 -19
- package/assets/themes/leipzig/bQ.svg +0 -22
- package/assets/themes/leipzig/bR.svg +0 -22
- package/assets/themes/leipzig/wB.svg +0 -20
- package/assets/themes/leipzig/wK.svg +0 -21
- package/assets/themes/leipzig/wN.svg +0 -19
- package/assets/themes/leipzig/wP.svg +0 -19
- package/assets/themes/leipzig/wQ.svg +0 -22
- package/assets/themes/leipzig/wR.svg +0 -22
- package/assets/themes/merida/bB.svg +0 -20
- package/assets/themes/merida/bK.svg +0 -21
- package/assets/themes/merida/bN.svg +0 -19
- package/assets/themes/merida/bP.svg +0 -19
- package/assets/themes/merida/bQ.svg +0 -22
- package/assets/themes/merida/bR.svg +0 -22
- package/assets/themes/merida/wB.svg +0 -20
- package/assets/themes/merida/wK.svg +0 -21
- package/assets/themes/merida/wN.svg +0 -19
- package/assets/themes/merida/wP.svg +0 -19
- package/assets/themes/merida/wQ.svg +0 -22
- package/assets/themes/merida/wR.svg +0 -22
package/dist/index.d.ts
CHANGED
|
@@ -34,12 +34,17 @@ interface SvgAssetSource {
|
|
|
34
34
|
kind: "svg";
|
|
35
35
|
source: string;
|
|
36
36
|
}
|
|
37
|
+
interface PngAssetSource {
|
|
38
|
+
kind: "png";
|
|
39
|
+
source: string;
|
|
40
|
+
}
|
|
41
|
+
type ThemeAssetSource = SvgAssetSource | PngAssetSource;
|
|
37
42
|
interface ThemeDefinition {
|
|
38
43
|
name: string;
|
|
39
44
|
displayName: string;
|
|
40
45
|
license: string;
|
|
41
46
|
attribution: string;
|
|
42
|
-
pieces: Record<PieceKey,
|
|
47
|
+
pieces: Record<PieceKey, ThemeAssetSource>;
|
|
43
48
|
}
|
|
44
49
|
interface BoardColors {
|
|
45
50
|
lightSquare?: string;
|
|
@@ -105,4 +110,4 @@ declare function renderChess(options: RenderChessOptions): Promise<Buffer>;
|
|
|
105
110
|
|
|
106
111
|
declare function registerTheme(theme: ThemeDefinition): ThemeDefinition;
|
|
107
112
|
|
|
108
|
-
export { type BoardArray, type BoardCell, type BoardColors, ChessImageGenerator, type ChessImageGeneratorOptions, IOError, type Padding, ParseError, type PieceKey, type PieceStyle, type RenderChessOptions, RenderError, type RenderOptions, type ResolvedColors, type ResolvedRenderOptions, type Square, type SvgAssetSource, type ThemeDefinition, ThemeError, ValidationError, registerTheme, renderChess };
|
|
113
|
+
export { type BoardArray, type BoardCell, type BoardColors, ChessImageGenerator, type ChessImageGeneratorOptions, IOError, type Padding, ParseError, type PieceKey, type PieceStyle, type PngAssetSource, type RenderChessOptions, RenderError, type RenderOptions, type ResolvedColors, type ResolvedRenderOptions, type Square, type SvgAssetSource, type ThemeAssetSource, type ThemeDefinition, ThemeError, ValidationError, registerTheme, renderChess };
|
package/dist/index.js
CHANGED
|
@@ -236,6 +236,7 @@ import { readFile } from "fs/promises";
|
|
|
236
236
|
import { createCanvas, loadImage } from "canvas";
|
|
237
237
|
import { Resvg } from "@resvg/resvg-js";
|
|
238
238
|
var svgSourceCache = new SourceAssetCache();
|
|
239
|
+
var imageBufferCache = new SourceAssetCache();
|
|
239
240
|
async function readSvgSource(filePath) {
|
|
240
241
|
const cached = svgSourceCache.get(filePath);
|
|
241
242
|
if (cached) {
|
|
@@ -249,6 +250,19 @@ async function readSvgSource(filePath) {
|
|
|
249
250
|
throw new RenderError(`Failed to read SVG asset: ${filePath}`, { cause: error });
|
|
250
251
|
}
|
|
251
252
|
}
|
|
253
|
+
async function readBinaryAsset(filePath) {
|
|
254
|
+
const cached = imageBufferCache.get(filePath);
|
|
255
|
+
if (cached) {
|
|
256
|
+
return cached;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
const source = await readFile(filePath);
|
|
260
|
+
imageBufferCache.set(filePath, source);
|
|
261
|
+
return source;
|
|
262
|
+
} catch (error) {
|
|
263
|
+
throw new RenderError(`Failed to read image asset: ${filePath}`, { cause: error });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
252
266
|
async function rasterizeSvgAsset(filePath, squareSize) {
|
|
253
267
|
try {
|
|
254
268
|
const svgSource = await readSvgSource(filePath);
|
|
@@ -268,6 +282,24 @@ async function rasterizeSvgAsset(filePath, squareSize) {
|
|
|
268
282
|
throw new RenderError(`Failed to rasterize SVG asset: ${filePath}`, { cause: error });
|
|
269
283
|
}
|
|
270
284
|
}
|
|
285
|
+
async function rasterizePngAsset(filePath, squareSize) {
|
|
286
|
+
try {
|
|
287
|
+
const pngSource = await readBinaryAsset(filePath);
|
|
288
|
+
const image = await loadImage(pngSource);
|
|
289
|
+
const canvas = createCanvas(squareSize, squareSize);
|
|
290
|
+
const context = canvas.getContext("2d");
|
|
291
|
+
context.drawImage(image, 0, 0, squareSize, squareSize);
|
|
292
|
+
return canvas;
|
|
293
|
+
} catch (error) {
|
|
294
|
+
throw new RenderError(`Failed to rasterize PNG asset: ${filePath}`, { cause: error });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function rasterizeThemeAsset(asset, squareSize) {
|
|
298
|
+
if (asset.kind === "svg") {
|
|
299
|
+
return rasterizeSvgAsset(asset.source, squareSize);
|
|
300
|
+
}
|
|
301
|
+
return rasterizePngAsset(asset.source, squareSize);
|
|
302
|
+
}
|
|
271
303
|
|
|
272
304
|
// src/render/canvas-renderer.ts
|
|
273
305
|
var pieceRasterCache = new RasterAssetCache();
|
|
@@ -276,13 +308,13 @@ function isDarkSquare(square) {
|
|
|
276
308
|
const rankNumber = Number(square[1]);
|
|
277
309
|
return (fileIndex + rankNumber) % 2 === 1;
|
|
278
310
|
}
|
|
279
|
-
async function getPieceRaster(themeName, pieceKey,
|
|
311
|
+
async function getPieceRaster(themeName, pieceKey, asset, squareSize) {
|
|
280
312
|
const cacheKey = createRasterCacheKey(themeName, pieceKey, squareSize, "png-canvas");
|
|
281
313
|
const cached = pieceRasterCache.get(cacheKey);
|
|
282
314
|
if (cached) {
|
|
283
315
|
return cached;
|
|
284
316
|
}
|
|
285
|
-
const raster = await
|
|
317
|
+
const raster = await rasterizeThemeAsset(asset, squareSize);
|
|
286
318
|
pieceRasterCache.set(cacheKey, raster);
|
|
287
319
|
return raster;
|
|
288
320
|
}
|
|
@@ -320,11 +352,10 @@ var CanvasPngRenderer = class {
|
|
|
320
352
|
if (!pieceKey) {
|
|
321
353
|
continue;
|
|
322
354
|
}
|
|
323
|
-
const assetPath2 = request.theme.pieces[pieceKey].source;
|
|
324
355
|
const raster = await getPieceRaster(
|
|
325
356
|
request.theme.name,
|
|
326
357
|
pieceKey,
|
|
327
|
-
|
|
358
|
+
request.theme.pieces[pieceKey],
|
|
328
359
|
Math.round(geometry.squareSize)
|
|
329
360
|
);
|
|
330
361
|
context.drawImage(
|
|
@@ -387,8 +418,8 @@ function validateThemeDefinition(theme) {
|
|
|
387
418
|
}
|
|
388
419
|
for (const pieceKey of REQUIRED_PIECES) {
|
|
389
420
|
const asset = theme.pieces[pieceKey];
|
|
390
|
-
if (!asset || asset.kind !== "svg" || !asset.source.trim()) {
|
|
391
|
-
throw new ThemeError(`Theme "${normalizedName}" is missing
|
|
421
|
+
if (!asset || asset.kind !== "svg" && asset.kind !== "png" || !asset.source.trim()) {
|
|
422
|
+
throw new ThemeError(`Theme "${normalizedName}" is missing asset ${pieceKey}`);
|
|
392
423
|
}
|
|
393
424
|
}
|
|
394
425
|
return {
|
|
@@ -436,9 +467,9 @@ var PIECE_KEYS = [
|
|
|
436
467
|
var initialized = false;
|
|
437
468
|
function assetPath(themeName, pieceKey) {
|
|
438
469
|
const candidates = [
|
|
439
|
-
resolve(__dirname, "../../assets/themes", themeName, `${pieceKey}.
|
|
440
|
-
resolve(__dirname, "../assets/themes", themeName, `${pieceKey}.
|
|
441
|
-
resolve(process.cwd(), "assets/themes", themeName, `${pieceKey}.
|
|
470
|
+
resolve(__dirname, "../../assets/themes", themeName, `${pieceKey}.png`),
|
|
471
|
+
resolve(__dirname, "../assets/themes", themeName, `${pieceKey}.png`),
|
|
472
|
+
resolve(process.cwd(), "assets/themes", themeName, `${pieceKey}.png`)
|
|
442
473
|
];
|
|
443
474
|
const match = candidates.find((candidate) => existsSync(candidate));
|
|
444
475
|
return match ?? candidates[0];
|
|
@@ -447,13 +478,13 @@ function createBuiltInTheme(themeName) {
|
|
|
447
478
|
return {
|
|
448
479
|
name: themeName,
|
|
449
480
|
displayName: themeName[0].toUpperCase() + themeName.slice(1),
|
|
450
|
-
license: "
|
|
451
|
-
attribution: "
|
|
481
|
+
license: "Derived from upstream chess-image-generator resource pack; original pack license not fully verified",
|
|
482
|
+
attribution: "Derived from andyruwruw/chess-image-generator bundled resources; upstream README cites Marcel van Kervinck as source",
|
|
452
483
|
pieces: Object.fromEntries(
|
|
453
484
|
PIECE_KEYS.map((pieceKey) => [
|
|
454
485
|
pieceKey,
|
|
455
486
|
{
|
|
456
|
-
kind: "
|
|
487
|
+
kind: "png",
|
|
457
488
|
source: assetPath(themeName, pieceKey)
|
|
458
489
|
}
|
|
459
490
|
])
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/types/errors.ts","../src/core/parsers.ts","../src/core/board.ts","../src/core/validators.ts","../src/core/highlights.ts","../src/render/canvas-renderer.ts","../src/core/geometry.ts","../src/render/asset-cache.ts","../src/render/rasterizer.ts","../src/utils/io.ts","../src/themes/builtins.ts","../src/themes/validation.ts","../src/themes/registry.ts","../src/themes/resolver.ts","../src/utils/normalization.ts","../src/api/class-api.ts","../src/api/functional-api.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","export class ValidationError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ParseError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ParseError\";\n }\n}\n\nexport class ThemeError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ThemeError\";\n }\n}\n\nexport class RenderError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"RenderError\";\n }\n}\n\nexport class IOError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"IOError\";\n }\n}\n","import { Chess } from \"chess.js\";\nimport type { BoardArray, BoardCell, PieceKey } from \"../types/types\";\nimport { ParseError, ValidationError } from \"../types/errors\";\nimport { createEmptyBoardPosition, FILES } from \"./board\";\nimport { validateBoardArray } from \"./validators\";\n\nconst PIECE_SYMBOL_TO_KEY: Record<string, PieceKey> = {\n K: \"wK\",\n Q: \"wQ\",\n R: \"wR\",\n B: \"wB\",\n N: \"wN\",\n P: \"wP\",\n k: \"bK\",\n q: \"bQ\",\n r: \"bR\",\n b: \"bB\",\n n: \"bN\",\n p: \"bP\",\n};\n\nfunction chessBoardToBoardArray(board: ReturnType<Chess[\"board\"]>): BoardArray {\n return board.map((rank) =>\n rank.map((piece): BoardCell => {\n if (!piece) {\n return null;\n }\n\n return piece.color === \"w\" ? piece.type.toUpperCase() : piece.type;\n }),\n );\n}\n\nexport function parseFEN(fen: string) {\n const chess = new Chess();\n\n try {\n chess.load(fen);\n } catch (error) {\n throw new ParseError(\"Invalid FEN\", { cause: error });\n }\n\n return parseBoardArray(chessBoardToBoardArray(chess.board()));\n}\n\nexport function parsePGN(pgn: string) {\n const chess = new Chess();\n\n try {\n chess.loadPgn(pgn);\n } catch (error) {\n throw new ParseError(\"Invalid PGN\", { cause: error });\n }\n\n return parseBoardArray(chessBoardToBoardArray(chess.board()));\n}\n\nexport function parseBoardArray(board: BoardArray) {\n const validatedBoard = validateBoardArray(board);\n const position = createEmptyBoardPosition();\n\n validatedBoard.forEach((rank, rankIndex) => {\n rank.forEach((cell, fileIndex) => {\n if (cell === null) {\n return;\n }\n\n const pieceKey = PIECE_SYMBOL_TO_KEY[cell];\n\n if (!pieceKey) {\n throw new ValidationError(`Invalid board piece: ${cell}`);\n }\n\n const square = `${FILES[fileIndex]}${8 - rankIndex}` as keyof typeof position.squares;\n position.squares[square] = pieceKey;\n });\n });\n\n return position;\n}\n","import type { PieceKey, Square } from \"../types/types\";\n\nexport const FILES = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"] as const;\nexport const RANKS = [\"8\", \"7\", \"6\", \"5\", \"4\", \"3\", \"2\", \"1\"] as const;\n\nexport const SQUARES: Square[] = RANKS.flatMap((rank) =>\n FILES.map((file) => `${file}${rank}`),\n);\n\nexport interface BoardPosition {\n squares: Record<Square, PieceKey | null>;\n}\n\nexport function createEmptyBoardPosition(): BoardPosition {\n return {\n squares: Object.fromEntries(\n SQUARES.map((square) => [square, null]),\n ) as Record<Square, PieceKey | null>,\n };\n}\n","import type { BoardArray, BoardCell, Padding, Square } from \"../types/types\";\nimport { ValidationError } from \"../types/errors\";\n\nconst SQUARE_PATTERN = /^[a-h][1-8]$/;\nconst PIECE_PATTERN = /^[prnbqkPRNBQK]$/;\nconst BUILT_IN_THEME_PATTERN = /^(merida|alpha|cburnett|cheq|leipzig)$/;\n\nexport function validateSize(size: number): number {\n if (!Number.isFinite(size) || size <= 0) {\n throw new ValidationError(`Invalid board size: ${size}`);\n }\n\n return Math.round(size);\n}\n\nexport function normalizePadding(padding?: number[] | Padding): Padding {\n const candidate = padding ?? [0, 0, 0, 0];\n\n if (\n !Array.isArray(candidate) ||\n candidate.length !== 4 ||\n candidate.some((value) => !Number.isFinite(value) || value < 0)\n ) {\n throw new ValidationError(\"Padding must be a 4-item array of non-negative numbers\");\n }\n\n return [\n Math.round(candidate[0]),\n Math.round(candidate[1]),\n Math.round(candidate[2]),\n Math.round(candidate[3]),\n ];\n}\n\nexport function validateSquare(square: string): Square {\n const normalized = square.trim().toLowerCase();\n\n if (!SQUARE_PATTERN.test(normalized)) {\n throw new ValidationError(`Invalid square: ${square}`);\n }\n\n return normalized;\n}\n\nexport function validateBoardCell(cell: BoardCell): BoardCell {\n if (cell === null || cell === \"\" || cell === \" \") {\n return null;\n }\n\n if (typeof cell !== \"string\" || !PIECE_PATTERN.test(cell)) {\n throw new ValidationError(`Invalid board piece: ${String(cell)}`);\n }\n\n return cell;\n}\n\nexport function validateBoardArray(board: BoardArray): BoardArray {\n if (!Array.isArray(board) || board.length !== 8) {\n throw new ValidationError(\"Board array must have exactly 8 ranks\");\n }\n\n return board.map((rank, rankIndex) => {\n if (!Array.isArray(rank) || rank.length !== 8) {\n throw new ValidationError(`Board rank ${rankIndex} must contain exactly 8 files`);\n }\n\n return rank.map(validateBoardCell);\n });\n}\n\nexport function validateStyleName(style: string): string {\n const normalized = style.trim().toLowerCase();\n\n if (!BUILT_IN_THEME_PATTERN.test(normalized)) {\n throw new ValidationError(`Unknown built-in style: ${style}`);\n }\n\n return normalized;\n}\n\nexport function validateThemeName(name: string): string {\n const normalized = name.trim().toLowerCase();\n\n if (!/^[a-z0-9-]+$/.test(normalized)) {\n throw new ValidationError(`Invalid theme name: ${name}`);\n }\n\n return normalized;\n}\n","import type { Square } from \"../types/types\";\nimport { validateSquare } from \"./validators\";\n\nexport function normalizeHighlights(input: string[]): Square[] {\n return [...new Set(input.map(validateSquare))].sort();\n}\n","import { createCanvas } from \"canvas\";\nimport { SQUARES } from \"../core/board\";\nimport { createBoardGeometry } from \"../core/geometry\";\nimport { RenderError } from \"../types/errors\";\nimport { createRasterCacheKey, RasterAssetCache } from \"./asset-cache\";\nimport type { RenderRequest, Renderer } from \"./renderer\";\nimport { rasterizeSvgAsset } from \"./rasterizer\";\n\nconst pieceRasterCache = new RasterAssetCache<Awaited<ReturnType<typeof rasterizeSvgAsset>>>();\n\nfunction isDarkSquare(square: string): boolean {\n const fileIndex = square.charCodeAt(0) - 97;\n const rankNumber = Number(square[1]);\n return (fileIndex + rankNumber) % 2 === 1;\n}\n\nasync function getPieceRaster(themeName: string, pieceKey: string, assetPath: string, squareSize: number) {\n const cacheKey = createRasterCacheKey(themeName, pieceKey, squareSize, \"png-canvas\");\n const cached = pieceRasterCache.get(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const raster = await rasterizeSvgAsset(assetPath, squareSize);\n pieceRasterCache.set(cacheKey, raster);\n return raster;\n}\n\nexport class CanvasPngRenderer implements Renderer<Buffer> {\n async render(request: RenderRequest): Promise<Buffer> {\n try {\n const geometry = createBoardGeometry({\n size: request.size,\n padding: request.padding,\n flipped: request.flipped,\n });\n\n const canvas = createCanvas(geometry.imageWidth, geometry.imageHeight);\n const context = canvas.getContext(\"2d\");\n\n context.fillStyle = request.colors.lightSquare;\n context.fillRect(0, 0, geometry.imageWidth, geometry.imageHeight);\n\n for (const square of SQUARES) {\n const squareGeometry = geometry.squares[square];\n context.fillStyle = isDarkSquare(square)\n ? request.colors.darkSquare\n : request.colors.lightSquare;\n context.fillRect(\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n\n if (request.highlights.includes(square)) {\n context.fillStyle = request.colors.highlight;\n context.fillRect(\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n }\n\n const pieceKey = request.board.squares[square];\n if (!pieceKey) {\n continue;\n }\n\n const assetPath = request.theme.pieces[pieceKey].source;\n const raster = await getPieceRaster(\n request.theme.name,\n pieceKey,\n assetPath,\n Math.round(geometry.squareSize),\n );\n context.drawImage(\n raster,\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n }\n\n return canvas.toBuffer(\"image/png\");\n } catch (error) {\n if (error instanceof RenderError) {\n throw error;\n }\n\n throw new RenderError(\"Failed to render chess board\", { cause: error });\n }\n }\n}\n","import type { Padding, Square } from \"../types/types\";\nimport { SQUARES } from \"./board\";\n\nexport interface SquareGeometry {\n x: number;\n y: number;\n size: number;\n}\n\nexport interface BoardGeometry {\n imageWidth: number;\n imageHeight: number;\n squareSize: number;\n boardX: number;\n boardY: number;\n boardSize: number;\n squares: Record<Square, SquareGeometry>;\n}\n\ninterface BoardGeometryOptions {\n size: number;\n padding: Padding;\n flipped: boolean;\n}\n\nexport function createBoardGeometry({\n size,\n padding,\n flipped,\n}: BoardGeometryOptions): BoardGeometry {\n const [top, right, bottom, left] = padding;\n const squareSize = size / 8;\n\n const squares = Object.fromEntries(\n SQUARES.map((square, index) => {\n const fileIndex = index % 8;\n const rankIndex = Math.floor(index / 8);\n\n const x = left + (flipped ? 7 - fileIndex : fileIndex) * squareSize;\n const y = top + (flipped ? 7 - rankIndex : rankIndex) * squareSize;\n\n return [square, { x, y, size: squareSize }];\n }),\n ) as Record<Square, SquareGeometry>;\n\n return {\n imageWidth: left + size + right,\n imageHeight: top + size + bottom,\n squareSize,\n boardX: left,\n boardY: top,\n boardSize: size,\n squares,\n };\n}\n","export function createRasterCacheKey(\n themeName: string,\n pieceKey: string,\n squareSize: number,\n backend: string,\n): string {\n return `${themeName}:${pieceKey}:${squareSize}:${backend}`;\n}\n\nexport class RasterAssetCache<T> {\n private readonly cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n}\n\nexport class SourceAssetCache<T> {\n private readonly cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { createCanvas, loadImage } from \"canvas\";\nimport { Resvg } from \"@resvg/resvg-js\";\nimport { RenderError } from \"../types/errors\";\nimport { SourceAssetCache } from \"./asset-cache\";\n\nconst svgSourceCache = new SourceAssetCache<string>();\n\nasync function readSvgSource(filePath: string): Promise<string> {\n const cached = svgSourceCache.get(filePath);\n\n if (cached) {\n return cached;\n }\n\n try {\n const source = await readFile(filePath, \"utf8\");\n svgSourceCache.set(filePath, source);\n return source;\n } catch (error) {\n throw new RenderError(`Failed to read SVG asset: ${filePath}`, { cause: error });\n }\n}\n\nexport async function rasterizeSvgAsset(filePath: string, squareSize: number) {\n try {\n const svgSource = await readSvgSource(filePath);\n const resvg = new Resvg(svgSource, {\n fitTo: {\n mode: \"width\",\n value: squareSize,\n },\n });\n const pngBuffer = resvg.render().asPng();\n const image = await loadImage(pngBuffer);\n const canvas = createCanvas(squareSize, squareSize);\n const context = canvas.getContext(\"2d\");\n context.drawImage(image, 0, 0, squareSize, squareSize);\n return canvas;\n } catch (error) {\n throw new RenderError(`Failed to rasterize SVG asset: ${filePath}`, { cause: error });\n }\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { IOError } from \"../types/errors\";\n\nexport async function writeBufferToFile(filePath: string, buffer: Buffer): Promise<void> {\n try {\n await writeFile(filePath, buffer);\n } catch (error) {\n throw new IOError(`Failed to write file: ${filePath}`, { cause: error });\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PieceKey, PieceStyle, ThemeDefinition } from \"../types/types\";\nimport { registerTheme } from \"./registry\";\n\nexport const builtInThemeNames = [\n \"merida\",\n \"alpha\",\n \"cburnett\",\n \"cheq\",\n \"leipzig\",\n] as const satisfies readonly PieceStyle[];\n\nconst PIECE_KEYS: PieceKey[] = [\n \"wK\",\n \"wQ\",\n \"wR\",\n \"wB\",\n \"wN\",\n \"wP\",\n \"bK\",\n \"bQ\",\n \"bR\",\n \"bB\",\n \"bN\",\n \"bP\",\n];\n\nlet initialized = false;\n\nfunction assetPath(themeName: PieceStyle, pieceKey: PieceKey): string {\n const candidates = [\n resolve(__dirname, \"../../assets/themes\", themeName, `${pieceKey}.svg`),\n resolve(__dirname, \"../assets/themes\", themeName, `${pieceKey}.svg`),\n resolve(process.cwd(), \"assets/themes\", themeName, `${pieceKey}.svg`),\n ];\n\n const match = candidates.find((candidate) => existsSync(candidate));\n return match ?? candidates[0];\n}\n\nfunction createBuiltInTheme(themeName: PieceStyle): ThemeDefinition {\n return {\n name: themeName,\n displayName: themeName[0].toUpperCase() + themeName.slice(1),\n license: \"MIT\",\n attribution: \"Project-authored built-in SVG theme\",\n pieces: Object.fromEntries(\n PIECE_KEYS.map((pieceKey) => [\n pieceKey,\n {\n kind: \"svg\",\n source: assetPath(themeName, pieceKey),\n },\n ]),\n ) as ThemeDefinition[\"pieces\"],\n };\n}\n\nexport function initializeBuiltInThemes(): void {\n if (initialized) {\n return;\n }\n\n for (const themeName of builtInThemeNames) {\n registerTheme(createBuiltInTheme(themeName));\n }\n\n initialized = true;\n}\n\nexport function resetBuiltInThemesForTesting(): void {\n initialized = false;\n}\n","import { validateThemeName } from \"../core/validators\";\nimport { ThemeError, ValidationError } from \"../types/errors\";\nimport type { PieceKey, ThemeDefinition } from \"../types/types\";\n\nconst REQUIRED_PIECES: PieceKey[] = [\n \"wK\",\n \"wQ\",\n \"wR\",\n \"wB\",\n \"wN\",\n \"wP\",\n \"bK\",\n \"bQ\",\n \"bR\",\n \"bB\",\n \"bN\",\n \"bP\",\n];\n\nexport function validateThemeDefinition(theme: ThemeDefinition): ThemeDefinition {\n const normalizedName = validateThemeName(theme.name);\n\n if (!theme.displayName.trim()) {\n throw new ValidationError(\"Theme displayName is required\");\n }\n\n if (!theme.license.trim()) {\n throw new ValidationError(\"Theme license is required\");\n }\n\n if (!theme.attribution.trim()) {\n throw new ValidationError(\"Theme attribution is required\");\n }\n\n for (const pieceKey of REQUIRED_PIECES) {\n const asset = theme.pieces[pieceKey];\n\n if (!asset || asset.kind !== \"svg\" || !asset.source.trim()) {\n throw new ThemeError(`Theme \"${normalizedName}\" is missing SVG asset ${pieceKey}`);\n }\n }\n\n return {\n ...theme,\n name: normalizedName,\n };\n}\n","import type { ThemeDefinition } from \"../types/types\";\nimport { ThemeError } from \"../types/errors\";\nimport { validateThemeDefinition } from \"./validation\";\n\nconst registry = new Map<string, ThemeDefinition>();\n\nexport function registerTheme(theme: ThemeDefinition): ThemeDefinition {\n const validatedTheme = validateThemeDefinition(theme);\n\n if (registry.has(validatedTheme.name)) {\n throw new ThemeError(`Theme \"${validatedTheme.name}\" is already registered`);\n }\n\n registry.set(validatedTheme.name, validatedTheme);\n return validatedTheme;\n}\n\nexport function getTheme(name: string): ThemeDefinition | undefined {\n return registry.get(name.trim().toLowerCase());\n}\n\nexport function clearThemeRegistryForTesting(): void {\n registry.clear();\n}\n","import type { PieceStyle, ThemeDefinition } from \"../types/types\";\nimport { ThemeError, ValidationError } from \"../types/errors\";\nimport { initializeBuiltInThemes } from \"./builtins\";\nimport { getTheme } from \"./registry\";\nimport { validateThemeDefinition } from \"./validation\";\n\ninterface ResolveThemeOptions {\n theme?: string | ThemeDefinition;\n style?: PieceStyle;\n}\n\nexport function resolveTheme({ theme, style }: ResolveThemeOptions): ThemeDefinition {\n initializeBuiltInThemes();\n\n if (typeof theme === \"object\" && theme !== null) {\n try {\n return validateThemeDefinition(theme);\n } catch (error) {\n if (error instanceof ThemeError) {\n throw error;\n }\n\n if (error instanceof ValidationError) {\n throw new ThemeError(error.message, { cause: error });\n }\n\n throw error;\n }\n }\n\n const requestedName = typeof theme === \"string\" ? theme : style ?? \"merida\";\n const resolvedTheme = getTheme(requestedName);\n\n if (!resolvedTheme) {\n throw new ThemeError(`Unknown theme: ${requestedName}`);\n }\n\n return resolvedTheme;\n}\n","import type {\n BoardColors,\n Padding,\n RenderOptions,\n ResolvedColors,\n Square,\n ThemeDefinition,\n} from \"../types/types\";\nimport { normalizeHighlights } from \"../core/highlights\";\nimport { normalizePadding, validateSize } from \"../core/validators\";\nimport { resolveTheme } from \"../themes/resolver\";\n\nexport const DEFAULT_SIZE = 480;\nexport const DEFAULT_PADDING: Padding = [0, 0, 0, 0];\nexport const DEFAULT_COLORS: ResolvedColors = {\n lightSquare: \"#f0d9b5\",\n darkSquare: \"#b58863\",\n highlight: \"rgba(255, 206, 0, 0.45)\",\n};\n\nexport function normalizeColors(colors?: BoardColors): ResolvedColors {\n return {\n lightSquare: colors?.lightSquare ?? DEFAULT_COLORS.lightSquare,\n darkSquare: colors?.darkSquare ?? DEFAULT_COLORS.darkSquare,\n highlight: colors?.highlight ?? DEFAULT_COLORS.highlight,\n };\n}\n\nexport function normalizeRenderInputs(options: RenderOptions & { highlightSquares?: Square[] }): {\n size: number;\n padding: Padding;\n flipped: boolean;\n theme: ThemeDefinition;\n highlightSquares: Square[];\n colors: ResolvedColors;\n} {\n return {\n size: validateSize(options.size ?? DEFAULT_SIZE),\n padding: normalizePadding(options.padding ?? DEFAULT_PADDING),\n flipped: options.flipped ?? false,\n theme: resolveTheme({\n theme: options.theme,\n style: options.style,\n }),\n highlightSquares: normalizeHighlights(options.highlightSquares ?? []),\n colors: normalizeColors(options.colors),\n };\n}\n","import { parseBoardArray, parseFEN, parsePGN } from \"../core/parsers\";\nimport { normalizeHighlights } from \"../core/highlights\";\nimport { ValidationError } from \"../types/errors\";\nimport type {\n BoardArray,\n ChessImageGeneratorOptions,\n RenderOptions,\n} from \"../types/types\";\nimport { CanvasPngRenderer } from \"../render/canvas-renderer\";\nimport { writeBufferToFile } from \"../utils/io\";\nimport { normalizeRenderInputs } from \"../utils/normalization\";\nimport type { BoardPosition } from \"../core/board\";\n\nexport class ChessImageGenerator {\n private position: BoardPosition | null = null;\n\n private readonly defaults: RenderOptions;\n\n private highlights: string[] = [];\n\n constructor(options: ChessImageGeneratorOptions = {}) {\n this.defaults = { ...options };\n normalizeRenderInputs({\n ...this.defaults,\n highlightSquares: [],\n });\n }\n\n async loadFEN(fen: string): Promise<void> {\n this.position = parseFEN(fen);\n this.clearHighlights();\n }\n\n async loadPGN(pgn: string): Promise<void> {\n this.position = parsePGN(pgn);\n this.clearHighlights();\n }\n\n async loadBoard(board: BoardArray): Promise<void> {\n this.position = parseBoardArray(board);\n this.clearHighlights();\n }\n\n setHighlights(squares: string[]): void {\n this.highlights = normalizeHighlights(squares);\n }\n\n clearHighlights(): void {\n this.highlights = [];\n }\n\n async toBuffer(): Promise<Buffer> {\n if (!this.position) {\n throw new ValidationError(\"No board position loaded\");\n }\n\n const renderer = new CanvasPngRenderer();\n const normalized = normalizeRenderInputs({\n ...this.defaults,\n highlightSquares: this.highlights,\n });\n\n return renderer.render({\n board: this.position,\n theme: normalized.theme,\n highlights: normalized.highlightSquares,\n size: normalized.size,\n padding: normalized.padding,\n flipped: normalized.flipped,\n colors: normalized.colors,\n });\n }\n\n async toFile(filePath: string): Promise<void> {\n const buffer = await this.toBuffer();\n await writeBufferToFile(filePath, buffer);\n }\n}\n","import { parseBoardArray, parseFEN, parsePGN } from \"../core/parsers\";\nimport { ValidationError } from \"../types/errors\";\nimport type { RenderChessOptions } from \"../types/types\";\nimport { CanvasPngRenderer } from \"../render/canvas-renderer\";\nimport { normalizeRenderInputs } from \"../utils/normalization\";\n\nfunction parseInputPosition(options: RenderChessOptions) {\n if (typeof options.fen === \"string\") {\n return parseFEN(options.fen);\n }\n\n if (typeof options.pgn === \"string\") {\n return parsePGN(options.pgn);\n }\n\n if (Array.isArray(options.board)) {\n return parseBoardArray(options.board);\n }\n\n throw new ValidationError(\"Exactly one of fen, pgn, or board must be provided\");\n}\n\nexport async function renderChess(options: RenderChessOptions): Promise<Buffer> {\n const provided = [\n typeof options.fen === \"string\" ? options.fen : undefined,\n typeof options.pgn === \"string\" ? options.pgn : undefined,\n Array.isArray(options.board) ? options.board : undefined,\n ].filter((value) => value !== undefined);\n\n if (provided.length !== 1) {\n throw new ValidationError(\"Exactly one of fen, pgn, or board must be provided\");\n }\n\n const position = parseInputPosition(options);\n const renderer = new CanvasPngRenderer();\n const normalized = normalizeRenderInputs(options);\n\n return renderer.render({\n board: position,\n theme: normalized.theme,\n highlights: normalized.highlightSquares,\n size: normalized.size,\n padding: normalized.padding,\n flipped: normalized.flipped,\n colors: normalized.colors,\n });\n}\n"],"mappings":"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","names":["createCanvas","assetPath","createCanvas"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/types/errors.ts","../src/core/parsers.ts","../src/core/board.ts","../src/core/validators.ts","../src/core/highlights.ts","../src/render/canvas-renderer.ts","../src/core/geometry.ts","../src/render/asset-cache.ts","../src/render/rasterizer.ts","../src/utils/io.ts","../src/themes/builtins.ts","../src/themes/validation.ts","../src/themes/registry.ts","../src/themes/resolver.ts","../src/utils/normalization.ts","../src/api/class-api.ts","../src/api/functional-api.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","export class ValidationError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ParseError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ParseError\";\n }\n}\n\nexport class ThemeError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ThemeError\";\n }\n}\n\nexport class RenderError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"RenderError\";\n }\n}\n\nexport class IOError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"IOError\";\n }\n}\n","import { Chess } from \"chess.js\";\nimport type { BoardArray, BoardCell, PieceKey } from \"../types/types\";\nimport { ParseError, ValidationError } from \"../types/errors\";\nimport { createEmptyBoardPosition, FILES } from \"./board\";\nimport { validateBoardArray } from \"./validators\";\n\nconst PIECE_SYMBOL_TO_KEY: Record<string, PieceKey> = {\n K: \"wK\",\n Q: \"wQ\",\n R: \"wR\",\n B: \"wB\",\n N: \"wN\",\n P: \"wP\",\n k: \"bK\",\n q: \"bQ\",\n r: \"bR\",\n b: \"bB\",\n n: \"bN\",\n p: \"bP\",\n};\n\nfunction chessBoardToBoardArray(board: ReturnType<Chess[\"board\"]>): BoardArray {\n return board.map((rank) =>\n rank.map((piece): BoardCell => {\n if (!piece) {\n return null;\n }\n\n return piece.color === \"w\" ? piece.type.toUpperCase() : piece.type;\n }),\n );\n}\n\nexport function parseFEN(fen: string) {\n const chess = new Chess();\n\n try {\n chess.load(fen);\n } catch (error) {\n throw new ParseError(\"Invalid FEN\", { cause: error });\n }\n\n return parseBoardArray(chessBoardToBoardArray(chess.board()));\n}\n\nexport function parsePGN(pgn: string) {\n const chess = new Chess();\n\n try {\n chess.loadPgn(pgn);\n } catch (error) {\n throw new ParseError(\"Invalid PGN\", { cause: error });\n }\n\n return parseBoardArray(chessBoardToBoardArray(chess.board()));\n}\n\nexport function parseBoardArray(board: BoardArray) {\n const validatedBoard = validateBoardArray(board);\n const position = createEmptyBoardPosition();\n\n validatedBoard.forEach((rank, rankIndex) => {\n rank.forEach((cell, fileIndex) => {\n if (cell === null) {\n return;\n }\n\n const pieceKey = PIECE_SYMBOL_TO_KEY[cell];\n\n if (!pieceKey) {\n throw new ValidationError(`Invalid board piece: ${cell}`);\n }\n\n const square = `${FILES[fileIndex]}${8 - rankIndex}` as keyof typeof position.squares;\n position.squares[square] = pieceKey;\n });\n });\n\n return position;\n}\n","import type { PieceKey, Square } from \"../types/types\";\n\nexport const FILES = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"] as const;\nexport const RANKS = [\"8\", \"7\", \"6\", \"5\", \"4\", \"3\", \"2\", \"1\"] as const;\n\nexport const SQUARES: Square[] = RANKS.flatMap((rank) =>\n FILES.map((file) => `${file}${rank}`),\n);\n\nexport interface BoardPosition {\n squares: Record<Square, PieceKey | null>;\n}\n\nexport function createEmptyBoardPosition(): BoardPosition {\n return {\n squares: Object.fromEntries(\n SQUARES.map((square) => [square, null]),\n ) as Record<Square, PieceKey | null>,\n };\n}\n","import type { BoardArray, BoardCell, Padding, Square } from \"../types/types\";\nimport { ValidationError } from \"../types/errors\";\n\nconst SQUARE_PATTERN = /^[a-h][1-8]$/;\nconst PIECE_PATTERN = /^[prnbqkPRNBQK]$/;\nconst BUILT_IN_THEME_PATTERN = /^(merida|alpha|cburnett|cheq|leipzig)$/;\n\nexport function validateSize(size: number): number {\n if (!Number.isFinite(size) || size <= 0) {\n throw new ValidationError(`Invalid board size: ${size}`);\n }\n\n return Math.round(size);\n}\n\nexport function normalizePadding(padding?: number[] | Padding): Padding {\n const candidate = padding ?? [0, 0, 0, 0];\n\n if (\n !Array.isArray(candidate) ||\n candidate.length !== 4 ||\n candidate.some((value) => !Number.isFinite(value) || value < 0)\n ) {\n throw new ValidationError(\"Padding must be a 4-item array of non-negative numbers\");\n }\n\n return [\n Math.round(candidate[0]),\n Math.round(candidate[1]),\n Math.round(candidate[2]),\n Math.round(candidate[3]),\n ];\n}\n\nexport function validateSquare(square: string): Square {\n const normalized = square.trim().toLowerCase();\n\n if (!SQUARE_PATTERN.test(normalized)) {\n throw new ValidationError(`Invalid square: ${square}`);\n }\n\n return normalized;\n}\n\nexport function validateBoardCell(cell: BoardCell): BoardCell {\n if (cell === null || cell === \"\" || cell === \" \") {\n return null;\n }\n\n if (typeof cell !== \"string\" || !PIECE_PATTERN.test(cell)) {\n throw new ValidationError(`Invalid board piece: ${String(cell)}`);\n }\n\n return cell;\n}\n\nexport function validateBoardArray(board: BoardArray): BoardArray {\n if (!Array.isArray(board) || board.length !== 8) {\n throw new ValidationError(\"Board array must have exactly 8 ranks\");\n }\n\n return board.map((rank, rankIndex) => {\n if (!Array.isArray(rank) || rank.length !== 8) {\n throw new ValidationError(`Board rank ${rankIndex} must contain exactly 8 files`);\n }\n\n return rank.map(validateBoardCell);\n });\n}\n\nexport function validateStyleName(style: string): string {\n const normalized = style.trim().toLowerCase();\n\n if (!BUILT_IN_THEME_PATTERN.test(normalized)) {\n throw new ValidationError(`Unknown built-in style: ${style}`);\n }\n\n return normalized;\n}\n\nexport function validateThemeName(name: string): string {\n const normalized = name.trim().toLowerCase();\n\n if (!/^[a-z0-9-]+$/.test(normalized)) {\n throw new ValidationError(`Invalid theme name: ${name}`);\n }\n\n return normalized;\n}\n","import type { Square } from \"../types/types\";\nimport { validateSquare } from \"./validators\";\n\nexport function normalizeHighlights(input: string[]): Square[] {\n return [...new Set(input.map(validateSquare))].sort();\n}\n","import { createCanvas } from \"canvas\";\nimport { SQUARES } from \"../core/board\";\nimport { createBoardGeometry } from \"../core/geometry\";\nimport { RenderError } from \"../types/errors\";\nimport type { ThemeAssetSource } from \"../types/types\";\nimport { createRasterCacheKey, RasterAssetCache } from \"./asset-cache\";\nimport type { RenderRequest, Renderer } from \"./renderer\";\nimport { rasterizeThemeAsset } from \"./rasterizer\";\n\nconst pieceRasterCache = new RasterAssetCache<Awaited<ReturnType<typeof rasterizeThemeAsset>>>();\n\nfunction isDarkSquare(square: string): boolean {\n const fileIndex = square.charCodeAt(0) - 97;\n const rankNumber = Number(square[1]);\n return (fileIndex + rankNumber) % 2 === 1;\n}\n\nasync function getPieceRaster(\n themeName: string,\n pieceKey: string,\n asset: ThemeAssetSource,\n squareSize: number,\n) {\n const cacheKey = createRasterCacheKey(themeName, pieceKey, squareSize, \"png-canvas\");\n const cached = pieceRasterCache.get(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const raster = await rasterizeThemeAsset(asset, squareSize);\n pieceRasterCache.set(cacheKey, raster);\n return raster;\n}\n\nexport class CanvasPngRenderer implements Renderer<Buffer> {\n async render(request: RenderRequest): Promise<Buffer> {\n try {\n const geometry = createBoardGeometry({\n size: request.size,\n padding: request.padding,\n flipped: request.flipped,\n });\n\n const canvas = createCanvas(geometry.imageWidth, geometry.imageHeight);\n const context = canvas.getContext(\"2d\");\n\n context.fillStyle = request.colors.lightSquare;\n context.fillRect(0, 0, geometry.imageWidth, geometry.imageHeight);\n\n for (const square of SQUARES) {\n const squareGeometry = geometry.squares[square];\n context.fillStyle = isDarkSquare(square)\n ? request.colors.darkSquare\n : request.colors.lightSquare;\n context.fillRect(\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n\n if (request.highlights.includes(square)) {\n context.fillStyle = request.colors.highlight;\n context.fillRect(\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n }\n\n const pieceKey = request.board.squares[square];\n if (!pieceKey) {\n continue;\n }\n\n const raster = await getPieceRaster(\n request.theme.name,\n pieceKey,\n request.theme.pieces[pieceKey],\n Math.round(geometry.squareSize),\n );\n context.drawImage(\n raster,\n squareGeometry.x,\n squareGeometry.y,\n squareGeometry.size,\n squareGeometry.size,\n );\n }\n\n return canvas.toBuffer(\"image/png\");\n } catch (error) {\n if (error instanceof RenderError) {\n throw error;\n }\n\n throw new RenderError(\"Failed to render chess board\", { cause: error });\n }\n }\n}\n","import type { Padding, Square } from \"../types/types\";\nimport { SQUARES } from \"./board\";\n\nexport interface SquareGeometry {\n x: number;\n y: number;\n size: number;\n}\n\nexport interface BoardGeometry {\n imageWidth: number;\n imageHeight: number;\n squareSize: number;\n boardX: number;\n boardY: number;\n boardSize: number;\n squares: Record<Square, SquareGeometry>;\n}\n\ninterface BoardGeometryOptions {\n size: number;\n padding: Padding;\n flipped: boolean;\n}\n\nexport function createBoardGeometry({\n size,\n padding,\n flipped,\n}: BoardGeometryOptions): BoardGeometry {\n const [top, right, bottom, left] = padding;\n const squareSize = size / 8;\n\n const squares = Object.fromEntries(\n SQUARES.map((square, index) => {\n const fileIndex = index % 8;\n const rankIndex = Math.floor(index / 8);\n\n const x = left + (flipped ? 7 - fileIndex : fileIndex) * squareSize;\n const y = top + (flipped ? 7 - rankIndex : rankIndex) * squareSize;\n\n return [square, { x, y, size: squareSize }];\n }),\n ) as Record<Square, SquareGeometry>;\n\n return {\n imageWidth: left + size + right,\n imageHeight: top + size + bottom,\n squareSize,\n boardX: left,\n boardY: top,\n boardSize: size,\n squares,\n };\n}\n","export function createRasterCacheKey(\n themeName: string,\n pieceKey: string,\n squareSize: number,\n backend: string,\n): string {\n return `${themeName}:${pieceKey}:${squareSize}:${backend}`;\n}\n\nexport class RasterAssetCache<T> {\n private readonly cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n}\n\nexport class SourceAssetCache<T> {\n private readonly cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { createCanvas, loadImage } from \"canvas\";\nimport { Resvg } from \"@resvg/resvg-js\";\nimport { RenderError } from \"../types/errors\";\nimport type { ThemeAssetSource } from \"../types/types\";\nimport { SourceAssetCache } from \"./asset-cache\";\n\nconst svgSourceCache = new SourceAssetCache<string>();\nconst imageBufferCache = new SourceAssetCache<Buffer>();\n\nasync function readSvgSource(filePath: string): Promise<string> {\n const cached = svgSourceCache.get(filePath);\n\n if (cached) {\n return cached;\n }\n\n try {\n const source = await readFile(filePath, \"utf8\");\n svgSourceCache.set(filePath, source);\n return source;\n } catch (error) {\n throw new RenderError(`Failed to read SVG asset: ${filePath}`, { cause: error });\n }\n}\n\nasync function readBinaryAsset(filePath: string): Promise<Buffer> {\n const cached = imageBufferCache.get(filePath);\n\n if (cached) {\n return cached;\n }\n\n try {\n const source = await readFile(filePath);\n imageBufferCache.set(filePath, source);\n return source;\n } catch (error) {\n throw new RenderError(`Failed to read image asset: ${filePath}`, { cause: error });\n }\n}\n\nasync function rasterizeSvgAsset(filePath: string, squareSize: number) {\n try {\n const svgSource = await readSvgSource(filePath);\n const resvg = new Resvg(svgSource, {\n fitTo: {\n mode: \"width\",\n value: squareSize,\n },\n });\n const pngBuffer = resvg.render().asPng();\n const image = await loadImage(pngBuffer);\n const canvas = createCanvas(squareSize, squareSize);\n const context = canvas.getContext(\"2d\");\n context.drawImage(image, 0, 0, squareSize, squareSize);\n return canvas;\n } catch (error) {\n throw new RenderError(`Failed to rasterize SVG asset: ${filePath}`, { cause: error });\n }\n}\n\nasync function rasterizePngAsset(filePath: string, squareSize: number) {\n try {\n const pngSource = await readBinaryAsset(filePath);\n const image = await loadImage(pngSource);\n const canvas = createCanvas(squareSize, squareSize);\n const context = canvas.getContext(\"2d\");\n context.drawImage(image, 0, 0, squareSize, squareSize);\n return canvas;\n } catch (error) {\n throw new RenderError(`Failed to rasterize PNG asset: ${filePath}`, { cause: error });\n }\n}\n\nexport async function rasterizeThemeAsset(asset: ThemeAssetSource, squareSize: number) {\n if (asset.kind === \"svg\") {\n return rasterizeSvgAsset(asset.source, squareSize);\n }\n\n return rasterizePngAsset(asset.source, squareSize);\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { IOError } from \"../types/errors\";\n\nexport async function writeBufferToFile(filePath: string, buffer: Buffer): Promise<void> {\n try {\n await writeFile(filePath, buffer);\n } catch (error) {\n throw new IOError(`Failed to write file: ${filePath}`, { cause: error });\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PieceKey, PieceStyle, ThemeDefinition } from \"../types/types\";\nimport { registerTheme } from \"./registry\";\n\nexport const builtInThemeNames = [\n \"merida\",\n \"alpha\",\n \"cburnett\",\n \"cheq\",\n \"leipzig\",\n] as const satisfies readonly PieceStyle[];\n\nconst PIECE_KEYS: PieceKey[] = [\n \"wK\",\n \"wQ\",\n \"wR\",\n \"wB\",\n \"wN\",\n \"wP\",\n \"bK\",\n \"bQ\",\n \"bR\",\n \"bB\",\n \"bN\",\n \"bP\",\n];\n\nlet initialized = false;\n\nfunction assetPath(themeName: PieceStyle, pieceKey: PieceKey): string {\n const candidates = [\n resolve(__dirname, \"../../assets/themes\", themeName, `${pieceKey}.png`),\n resolve(__dirname, \"../assets/themes\", themeName, `${pieceKey}.png`),\n resolve(process.cwd(), \"assets/themes\", themeName, `${pieceKey}.png`),\n ];\n\n const match = candidates.find((candidate) => existsSync(candidate));\n return match ?? candidates[0];\n}\n\nfunction createBuiltInTheme(themeName: PieceStyle): ThemeDefinition {\n return {\n name: themeName,\n displayName: themeName[0].toUpperCase() + themeName.slice(1),\n license: \"Derived from upstream chess-image-generator resource pack; original pack license not fully verified\",\n attribution:\n \"Derived from andyruwruw/chess-image-generator bundled resources; upstream README cites Marcel van Kervinck as source\",\n pieces: Object.fromEntries(\n PIECE_KEYS.map((pieceKey) => [\n pieceKey,\n {\n kind: \"png\",\n source: assetPath(themeName, pieceKey),\n },\n ]),\n ) as ThemeDefinition[\"pieces\"],\n };\n}\n\nexport function initializeBuiltInThemes(): void {\n if (initialized) {\n return;\n }\n\n for (const themeName of builtInThemeNames) {\n registerTheme(createBuiltInTheme(themeName));\n }\n\n initialized = true;\n}\n\nexport function resetBuiltInThemesForTesting(): void {\n initialized = false;\n}\n","import { validateThemeName } from \"../core/validators\";\nimport { ThemeError, ValidationError } from \"../types/errors\";\nimport type { PieceKey, ThemeDefinition } from \"../types/types\";\n\nconst REQUIRED_PIECES: PieceKey[] = [\n \"wK\",\n \"wQ\",\n \"wR\",\n \"wB\",\n \"wN\",\n \"wP\",\n \"bK\",\n \"bQ\",\n \"bR\",\n \"bB\",\n \"bN\",\n \"bP\",\n];\n\nexport function validateThemeDefinition(theme: ThemeDefinition): ThemeDefinition {\n const normalizedName = validateThemeName(theme.name);\n\n if (!theme.displayName.trim()) {\n throw new ValidationError(\"Theme displayName is required\");\n }\n\n if (!theme.license.trim()) {\n throw new ValidationError(\"Theme license is required\");\n }\n\n if (!theme.attribution.trim()) {\n throw new ValidationError(\"Theme attribution is required\");\n }\n\n for (const pieceKey of REQUIRED_PIECES) {\n const asset = theme.pieces[pieceKey];\n\n if (!asset || (asset.kind !== \"svg\" && asset.kind !== \"png\") || !asset.source.trim()) {\n throw new ThemeError(`Theme \"${normalizedName}\" is missing asset ${pieceKey}`);\n }\n }\n\n return {\n ...theme,\n name: normalizedName,\n };\n}\n","import type { ThemeDefinition } from \"../types/types\";\nimport { ThemeError } from \"../types/errors\";\nimport { validateThemeDefinition } from \"./validation\";\n\nconst registry = new Map<string, ThemeDefinition>();\n\nexport function registerTheme(theme: ThemeDefinition): ThemeDefinition {\n const validatedTheme = validateThemeDefinition(theme);\n\n if (registry.has(validatedTheme.name)) {\n throw new ThemeError(`Theme \"${validatedTheme.name}\" is already registered`);\n }\n\n registry.set(validatedTheme.name, validatedTheme);\n return validatedTheme;\n}\n\nexport function getTheme(name: string): ThemeDefinition | undefined {\n return registry.get(name.trim().toLowerCase());\n}\n\nexport function clearThemeRegistryForTesting(): void {\n registry.clear();\n}\n","import type { PieceStyle, ThemeDefinition } from \"../types/types\";\nimport { ThemeError, ValidationError } from \"../types/errors\";\nimport { initializeBuiltInThemes } from \"./builtins\";\nimport { getTheme } from \"./registry\";\nimport { validateThemeDefinition } from \"./validation\";\n\ninterface ResolveThemeOptions {\n theme?: string | ThemeDefinition;\n style?: PieceStyle;\n}\n\nexport function resolveTheme({ theme, style }: ResolveThemeOptions): ThemeDefinition {\n initializeBuiltInThemes();\n\n if (typeof theme === \"object\" && theme !== null) {\n try {\n return validateThemeDefinition(theme);\n } catch (error) {\n if (error instanceof ThemeError) {\n throw error;\n }\n\n if (error instanceof ValidationError) {\n throw new ThemeError(error.message, { cause: error });\n }\n\n throw error;\n }\n }\n\n const requestedName = typeof theme === \"string\" ? theme : style ?? \"merida\";\n const resolvedTheme = getTheme(requestedName);\n\n if (!resolvedTheme) {\n throw new ThemeError(`Unknown theme: ${requestedName}`);\n }\n\n return resolvedTheme;\n}\n","import type {\n BoardColors,\n Padding,\n RenderOptions,\n ResolvedColors,\n Square,\n ThemeDefinition,\n} from \"../types/types\";\nimport { normalizeHighlights } from \"../core/highlights\";\nimport { normalizePadding, validateSize } from \"../core/validators\";\nimport { resolveTheme } from \"../themes/resolver\";\n\nexport const DEFAULT_SIZE = 480;\nexport const DEFAULT_PADDING: Padding = [0, 0, 0, 0];\nexport const DEFAULT_COLORS: ResolvedColors = {\n lightSquare: \"#f0d9b5\",\n darkSquare: \"#b58863\",\n highlight: \"rgba(255, 206, 0, 0.45)\",\n};\n\nexport function normalizeColors(colors?: BoardColors): ResolvedColors {\n return {\n lightSquare: colors?.lightSquare ?? DEFAULT_COLORS.lightSquare,\n darkSquare: colors?.darkSquare ?? DEFAULT_COLORS.darkSquare,\n highlight: colors?.highlight ?? DEFAULT_COLORS.highlight,\n };\n}\n\nexport function normalizeRenderInputs(options: RenderOptions & { highlightSquares?: Square[] }): {\n size: number;\n padding: Padding;\n flipped: boolean;\n theme: ThemeDefinition;\n highlightSquares: Square[];\n colors: ResolvedColors;\n} {\n return {\n size: validateSize(options.size ?? DEFAULT_SIZE),\n padding: normalizePadding(options.padding ?? DEFAULT_PADDING),\n flipped: options.flipped ?? false,\n theme: resolveTheme({\n theme: options.theme,\n style: options.style,\n }),\n highlightSquares: normalizeHighlights(options.highlightSquares ?? []),\n colors: normalizeColors(options.colors),\n };\n}\n","import { parseBoardArray, parseFEN, parsePGN } from \"../core/parsers\";\nimport { normalizeHighlights } from \"../core/highlights\";\nimport { ValidationError } from \"../types/errors\";\nimport type {\n BoardArray,\n ChessImageGeneratorOptions,\n RenderOptions,\n} from \"../types/types\";\nimport { CanvasPngRenderer } from \"../render/canvas-renderer\";\nimport { writeBufferToFile } from \"../utils/io\";\nimport { normalizeRenderInputs } from \"../utils/normalization\";\nimport type { BoardPosition } from \"../core/board\";\n\nexport class ChessImageGenerator {\n private position: BoardPosition | null = null;\n\n private readonly defaults: RenderOptions;\n\n private highlights: string[] = [];\n\n constructor(options: ChessImageGeneratorOptions = {}) {\n this.defaults = { ...options };\n normalizeRenderInputs({\n ...this.defaults,\n highlightSquares: [],\n });\n }\n\n async loadFEN(fen: string): Promise<void> {\n this.position = parseFEN(fen);\n this.clearHighlights();\n }\n\n async loadPGN(pgn: string): Promise<void> {\n this.position = parsePGN(pgn);\n this.clearHighlights();\n }\n\n async loadBoard(board: BoardArray): Promise<void> {\n this.position = parseBoardArray(board);\n this.clearHighlights();\n }\n\n setHighlights(squares: string[]): void {\n this.highlights = normalizeHighlights(squares);\n }\n\n clearHighlights(): void {\n this.highlights = [];\n }\n\n async toBuffer(): Promise<Buffer> {\n if (!this.position) {\n throw new ValidationError(\"No board position loaded\");\n }\n\n const renderer = new CanvasPngRenderer();\n const normalized = normalizeRenderInputs({\n ...this.defaults,\n highlightSquares: this.highlights,\n });\n\n return renderer.render({\n board: this.position,\n theme: normalized.theme,\n highlights: normalized.highlightSquares,\n size: normalized.size,\n padding: normalized.padding,\n flipped: normalized.flipped,\n colors: normalized.colors,\n });\n }\n\n async toFile(filePath: string): Promise<void> {\n const buffer = await this.toBuffer();\n await writeBufferToFile(filePath, buffer);\n }\n}\n","import { parseBoardArray, parseFEN, parsePGN } from \"../core/parsers\";\nimport { ValidationError } from \"../types/errors\";\nimport type { RenderChessOptions } from \"../types/types\";\nimport { CanvasPngRenderer } from \"../render/canvas-renderer\";\nimport { normalizeRenderInputs } from \"../utils/normalization\";\n\nfunction parseInputPosition(options: RenderChessOptions) {\n if (typeof options.fen === \"string\") {\n return parseFEN(options.fen);\n }\n\n if (typeof options.pgn === \"string\") {\n return parsePGN(options.pgn);\n }\n\n if (Array.isArray(options.board)) {\n return parseBoardArray(options.board);\n }\n\n throw new ValidationError(\"Exactly one of fen, pgn, or board must be provided\");\n}\n\nexport async function renderChess(options: RenderChessOptions): Promise<Buffer> {\n const provided = [\n typeof options.fen === \"string\" ? options.fen : undefined,\n typeof options.pgn === \"string\" ? options.pgn : undefined,\n Array.isArray(options.board) ? options.board : undefined,\n ].filter((value) => value !== undefined);\n\n if (provided.length !== 1) {\n throw new ValidationError(\"Exactly one of fen, pgn, or board must be provided\");\n }\n\n const position = parseInputPosition(options);\n const renderer = new CanvasPngRenderer();\n const normalized = normalizeRenderInputs(options);\n\n return renderer.render({\n board: position,\n theme: normalized.theme,\n highlights: normalized.highlightSquares,\n size: normalized.size,\n padding: normalized.padding,\n flipped: normalized.flipped,\n colors: normalized.colors,\n });\n}\n"],"mappings":"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","names":["createCanvas","createCanvas"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chess2img",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Modern chess board image rendering for Node.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
"url": "https://github.com/ZiriloXXX/chess2img/issues"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/ZiriloXXX/chess2img#readme",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"chess",
|
|
16
|
+
"chessboard",
|
|
17
|
+
"fen",
|
|
18
|
+
"pgn",
|
|
19
|
+
"png",
|
|
20
|
+
"image",
|
|
21
|
+
"chess-image",
|
|
22
|
+
"chess-render"
|
|
23
|
+
],
|
|
14
24
|
"type": "module",
|
|
15
25
|
"main": "./dist/index.cjs",
|
|
16
26
|
"module": "./dist/index.js",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bB-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bB-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="50" cy="22" r="6" />
|
|
12
|
-
<path d="M40 27c8 2 16 10 16 21 0 6-2 11-6 16H34l6-10c2-4 3-7 3-12 0-5-2-9-3-15z" />
|
|
13
|
-
<path d="M54 36l8 8" stroke-linecap="round" />
|
|
14
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
15
|
-
|
|
16
|
-
</g>
|
|
17
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
18
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
19
|
-
</g>
|
|
20
|
-
</svg>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bK-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bK-shadow)">
|
|
10
|
-
|
|
11
|
-
<rect x="38" y="44" width="24" height="9" rx="3" />
|
|
12
|
-
<rect x="46" y="23" width="8" height="24" rx="2" />
|
|
13
|
-
<rect x="35" y="31" width="30" height="8" rx="2" />
|
|
14
|
-
<path d="M26 69h48l-5 11H31z" />
|
|
15
|
-
<path d="M33 69V56c0-13 9-23 19-23s19 10 19 23v13z" />
|
|
16
|
-
|
|
17
|
-
</g>
|
|
18
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
19
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
20
|
-
</g>
|
|
21
|
-
</svg>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bN-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bN-shadow)">
|
|
10
|
-
|
|
11
|
-
<path d="M34 66c0-17 4-31 16-42 5-5 13-8 18-6-2 4-3 8-2 12 4 2 7 6 8 11-5 0-9 1-13 4 4 5 6 12 6 21H34z" />
|
|
12
|
-
<circle cx="61" cy="33" r="2.5" />
|
|
13
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
14
|
-
|
|
15
|
-
</g>
|
|
16
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
17
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
18
|
-
</g>
|
|
19
|
-
</svg>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bP-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bP-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="50" cy="26" r="10" />
|
|
12
|
-
<path d="M37 69V58c0-9 6-17 13-17s13 8 13 17v11z" />
|
|
13
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
14
|
-
|
|
15
|
-
</g>
|
|
16
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
17
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
18
|
-
</g>
|
|
19
|
-
</svg>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bQ-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bQ-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="28" cy="33" r="5" />
|
|
12
|
-
<circle cx="40" cy="26" r="5" />
|
|
13
|
-
<circle cx="52" cy="24" r="5" />
|
|
14
|
-
<circle cx="64" cy="31" r="5" />
|
|
15
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
16
|
-
<path d="M30 66l6-26 12 12 12-15 4 29z" />
|
|
17
|
-
|
|
18
|
-
</g>
|
|
19
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
20
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
21
|
-
</g>
|
|
22
|
-
</svg>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-bR-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff08"/>
|
|
9
|
-
<g fill="#10243c" stroke="#4f9dff" stroke-width="2.2" filter="url(#alpha-bR-shadow)">
|
|
10
|
-
|
|
11
|
-
<rect x="29" y="23" width="42" height="11" rx="2" />
|
|
12
|
-
<rect x="33" y="18" width="8" height="10" rx="1" />
|
|
13
|
-
<rect x="46" y="18" width="8" height="10" rx="1" />
|
|
14
|
-
<rect x="59" y="18" width="8" height="10" rx="1" />
|
|
15
|
-
<path d="M32 69h40l-4 11H36z" />
|
|
16
|
-
<rect x="35" y="34" width="30" height="35" rx="4" />
|
|
17
|
-
|
|
18
|
-
</g>
|
|
19
|
-
<g fill="none" stroke="#f7fbff" stroke-width="2">
|
|
20
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
21
|
-
</g>
|
|
22
|
-
</svg>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wB-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wB-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="50" cy="22" r="6" />
|
|
12
|
-
<path d="M40 27c8 2 16 10 16 21 0 6-2 11-6 16H34l6-10c2-4 3-7 3-12 0-5-2-9-3-15z" />
|
|
13
|
-
<path d="M54 36l8 8" stroke-linecap="round" />
|
|
14
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
15
|
-
|
|
16
|
-
</g>
|
|
17
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
18
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
19
|
-
</g>
|
|
20
|
-
</svg>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wK-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wK-shadow)">
|
|
10
|
-
|
|
11
|
-
<rect x="38" y="44" width="24" height="9" rx="3" />
|
|
12
|
-
<rect x="46" y="23" width="8" height="24" rx="2" />
|
|
13
|
-
<rect x="35" y="31" width="30" height="8" rx="2" />
|
|
14
|
-
<path d="M26 69h48l-5 11H31z" />
|
|
15
|
-
<path d="M33 69V56c0-13 9-23 19-23s19 10 19 23v13z" />
|
|
16
|
-
|
|
17
|
-
</g>
|
|
18
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
19
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
20
|
-
</g>
|
|
21
|
-
</svg>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wN-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wN-shadow)">
|
|
10
|
-
|
|
11
|
-
<path d="M34 66c0-17 4-31 16-42 5-5 13-8 18-6-2 4-3 8-2 12 4 2 7 6 8 11-5 0-9 1-13 4 4 5 6 12 6 21H34z" />
|
|
12
|
-
<circle cx="61" cy="33" r="2.5" />
|
|
13
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
14
|
-
|
|
15
|
-
</g>
|
|
16
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
17
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
18
|
-
</g>
|
|
19
|
-
</svg>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wP-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wP-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="50" cy="26" r="10" />
|
|
12
|
-
<path d="M37 69V58c0-9 6-17 13-17s13 8 13 17v11z" />
|
|
13
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
14
|
-
|
|
15
|
-
</g>
|
|
16
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
17
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
18
|
-
</g>
|
|
19
|
-
</svg>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wQ-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wQ-shadow)">
|
|
10
|
-
|
|
11
|
-
<circle cx="28" cy="33" r="5" />
|
|
12
|
-
<circle cx="40" cy="26" r="5" />
|
|
13
|
-
<circle cx="52" cy="24" r="5" />
|
|
14
|
-
<circle cx="64" cy="31" r="5" />
|
|
15
|
-
<path d="M26 69h48l-4 11H30z" />
|
|
16
|
-
<path d="M30 66l6-26 12 12 12-15 4 29z" />
|
|
17
|
-
|
|
18
|
-
</g>
|
|
19
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
20
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
21
|
-
</g>
|
|
22
|
-
</svg>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
|
|
3
|
-
<defs>
|
|
4
|
-
<filter id="alpha-wR-shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
5
|
-
<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="#00000033"/>
|
|
6
|
-
</filter>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect x="12" y="12" width="76" height="76" rx="14" fill="#ffffff00"/>
|
|
9
|
-
<g fill="#f7fbff" stroke="#173a62" stroke-width="2.2" filter="url(#alpha-wR-shadow)">
|
|
10
|
-
|
|
11
|
-
<rect x="29" y="23" width="42" height="11" rx="2" />
|
|
12
|
-
<rect x="33" y="18" width="8" height="10" rx="1" />
|
|
13
|
-
<rect x="46" y="18" width="8" height="10" rx="1" />
|
|
14
|
-
<rect x="59" y="18" width="8" height="10" rx="1" />
|
|
15
|
-
<path d="M32 69h40l-4 11H36z" />
|
|
16
|
-
<rect x="35" y="34" width="30" height="35" rx="4" />
|
|
17
|
-
|
|
18
|
-
</g>
|
|
19
|
-
<g fill="none" stroke="#4f9dff" stroke-width="2">
|
|
20
|
-
<path d="M30 82h40" stroke-linecap="round" />
|
|
21
|
-
</g>
|
|
22
|
-
</svg>
|