chess2img 0.2.2 → 0.3.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 +38 -3
- package/dist/index.cjs +204 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +204 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ const png = await renderChess({
|
|
|
50
50
|
darkSquare: "#769656",
|
|
51
51
|
highlight: "rgba(246, 246, 105, 0.6)",
|
|
52
52
|
},
|
|
53
|
-
|
|
53
|
+
highlights: ["e2", "e4"],
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
await writeFile("board.png", png);
|
|
@@ -144,6 +144,38 @@ const png = await renderChess({
|
|
|
144
144
|
await writeFile("board-with-inside-coordinates.png", png);
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
+
### Circle Highlights
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { writeFile } from "node:fs/promises";
|
|
151
|
+
import { renderChess } from "chess2img";
|
|
152
|
+
|
|
153
|
+
const png = await renderChess({
|
|
154
|
+
fen: "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
|
|
155
|
+
size: 480,
|
|
156
|
+
style: "cburnett",
|
|
157
|
+
highlights: [{ square: "e4", style: "circle" }],
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await writeFile("board-with-circle-highlight.png", png);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Combined Fill And Circle Highlights
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { writeFile } from "node:fs/promises";
|
|
167
|
+
import { renderChess } from "chess2img";
|
|
168
|
+
|
|
169
|
+
const png = await renderChess({
|
|
170
|
+
fen: "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
|
|
171
|
+
size: 480,
|
|
172
|
+
style: "cburnett",
|
|
173
|
+
highlights: ["e4", { square: "e4", style: "circle" }],
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
await writeFile("board-with-fill-and-circle-highlights.png", png);
|
|
177
|
+
```
|
|
178
|
+
|
|
147
179
|
### Class API
|
|
148
180
|
|
|
149
181
|
```ts
|
|
@@ -241,7 +273,7 @@ Methods:
|
|
|
241
273
|
- `loadFEN(fen: string): Promise<void>`
|
|
242
274
|
- `loadPGN(pgn: string): Promise<void>`
|
|
243
275
|
- `loadBoard(board: BoardArray): Promise<void>`
|
|
244
|
-
- `setHighlights(
|
|
276
|
+
- `setHighlights(highlights: HighlightInput[]): void`
|
|
245
277
|
- `clearHighlights(): void`
|
|
246
278
|
- `toBuffer(): Promise<Buffer>`
|
|
247
279
|
- `toFile(filePath: string): Promise<void>`
|
|
@@ -261,7 +293,8 @@ Semantics:
|
|
|
261
293
|
- `flipped`: render from black's perspective when `true`
|
|
262
294
|
- `style`: built-in theme alias
|
|
263
295
|
- `theme`: built-in theme name, registered custom theme name, or inline `ThemeDefinition`
|
|
264
|
-
- `
|
|
296
|
+
- `highlights`: array of square strings or highlight objects such as `["e4", { square: "d5", style: "circle" }]`
|
|
297
|
+
- `highlightSquares`: compatibility alias for `highlights`
|
|
265
298
|
- `coordinates`: `boolean`, `"border"`, `"inside"`, or `{ enabled?: boolean; position?: "border" | "inside"; color?: string }`
|
|
266
299
|
- `colors.lightSquare`
|
|
267
300
|
- `colors.darkSquare`
|
|
@@ -269,6 +302,8 @@ Semantics:
|
|
|
269
302
|
|
|
270
303
|
`coordinates: false` or omitting the option disables labels. `coordinates: true` enables labels and chooses `border` mode when `borderSize > 0`, otherwise `inside` mode. Explicit `coordinates: "inside"` is always valid. Explicit `coordinates: "border"` requires `borderSize > 0` and throws `ValidationError` otherwise.
|
|
271
304
|
|
|
305
|
+
`highlights` is the preferred API. Each entry may be a square string for a filled highlight, or an object with `square`, `style`, `color`, `opacity`, and `lineWidth`. `highlightSquares` remains available for backward compatibility, but should not be used together with `highlights` in the same call.
|
|
306
|
+
|
|
272
307
|
Inside coordinates use automatic light/dark contrast by default, similar to chess.com. If `coordinates.color` is provided, that exact color is used instead. Border coordinates keep a single-color label style with `#333` as the default.
|
|
273
308
|
|
|
274
309
|
At very small valid sizes, the renderer suppresses coordinates when they cannot fit legibly in the available border band or edge-square area.
|
package/dist/index.cjs
CHANGED
|
@@ -187,6 +187,12 @@ function isCoordinatesOptions(value) {
|
|
|
187
187
|
function isCoordinatesPosition(value) {
|
|
188
188
|
return value === "border" || value === "inside";
|
|
189
189
|
}
|
|
190
|
+
function isHighlightOptions(value) {
|
|
191
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
192
|
+
}
|
|
193
|
+
function isHighlightStyle(value) {
|
|
194
|
+
return value === "fill" || value === "circle";
|
|
195
|
+
}
|
|
190
196
|
function validateCoordinatesOption(coordinates, borderSize) {
|
|
191
197
|
if (coordinates === void 0 || typeof coordinates === "boolean") {
|
|
192
198
|
return;
|
|
@@ -219,6 +225,52 @@ function validateCoordinatesOption(coordinates, borderSize) {
|
|
|
219
225
|
validateColorString(coordinates.color, "coordinates.color");
|
|
220
226
|
}
|
|
221
227
|
}
|
|
228
|
+
function validateHighlightEntry(entry) {
|
|
229
|
+
if (typeof entry === "string") {
|
|
230
|
+
validateSquare(entry);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!isHighlightOptions(entry)) {
|
|
234
|
+
throw new ValidationError("highlights entries must be square strings or highlight objects");
|
|
235
|
+
}
|
|
236
|
+
if (typeof entry.square !== "string") {
|
|
237
|
+
throw new ValidationError("highlight.square must be a valid algebraic square");
|
|
238
|
+
}
|
|
239
|
+
validateSquare(entry.square);
|
|
240
|
+
if (entry.style !== void 0 && !isHighlightStyle(entry.style)) {
|
|
241
|
+
throw new ValidationError("highlight.style must be 'fill' or 'circle'");
|
|
242
|
+
}
|
|
243
|
+
if (entry.color !== void 0) {
|
|
244
|
+
validateColorString(entry.color, "highlight.color");
|
|
245
|
+
}
|
|
246
|
+
if (entry.opacity !== void 0 && (!Number.isFinite(entry.opacity) || entry.opacity < 0 || entry.opacity > 1)) {
|
|
247
|
+
throw new ValidationError("highlight.opacity must be a finite number between 0 and 1");
|
|
248
|
+
}
|
|
249
|
+
if (entry.lineWidth !== void 0 && (!Number.isFinite(entry.lineWidth) || entry.lineWidth <= 0)) {
|
|
250
|
+
throw new ValidationError("highlight.lineWidth must be a finite number greater than 0");
|
|
251
|
+
}
|
|
252
|
+
if (entry.radius !== void 0 && (!Number.isFinite(entry.radius) || entry.radius <= 0 || entry.radius > 0.5)) {
|
|
253
|
+
throw new ValidationError("highlight.radius must be a finite number greater than 0 and at most 0.5");
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function validateHighlightOptions(highlights) {
|
|
257
|
+
if (highlights === void 0) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!Array.isArray(highlights)) {
|
|
261
|
+
throw new ValidationError("highlights must be an array");
|
|
262
|
+
}
|
|
263
|
+
for (const entry of highlights) {
|
|
264
|
+
validateHighlightEntry(entry);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function validateHighlightsInput(highlights, highlightSquares) {
|
|
268
|
+
if (highlights !== void 0 && highlightSquares !== void 0) {
|
|
269
|
+
throw new ValidationError("Use either highlights or highlightSquares, not both");
|
|
270
|
+
}
|
|
271
|
+
validateHighlightOptions(highlights);
|
|
272
|
+
validateHighlightOptions(highlightSquares);
|
|
273
|
+
}
|
|
222
274
|
|
|
223
275
|
// src/core/parsers.ts
|
|
224
276
|
var PIECE_SYMBOL_TO_KEY = {
|
|
@@ -282,11 +334,6 @@ function parseBoardArray(board) {
|
|
|
282
334
|
return position;
|
|
283
335
|
}
|
|
284
336
|
|
|
285
|
-
// src/core/highlights.ts
|
|
286
|
-
function normalizeHighlights(input) {
|
|
287
|
-
return [...new Set(input.map(validateSquare))].sort();
|
|
288
|
-
}
|
|
289
|
-
|
|
290
337
|
// src/render/canvas-renderer.ts
|
|
291
338
|
var import_canvas3 = require("canvas");
|
|
292
339
|
|
|
@@ -512,6 +559,23 @@ function resolveInsideLabelColor(request, square) {
|
|
|
512
559
|
}
|
|
513
560
|
return isDarkSquare(square) ? INSIDE_LIGHT_LABEL_COLOR : INSIDE_DARK_LABEL_COLOR;
|
|
514
561
|
}
|
|
562
|
+
function resolveHighlightOpacity(style, color, opacity) {
|
|
563
|
+
if (opacity !== void 0) {
|
|
564
|
+
return opacity;
|
|
565
|
+
}
|
|
566
|
+
if (style === "circle" || color !== void 0) {
|
|
567
|
+
return 0.9;
|
|
568
|
+
}
|
|
569
|
+
return 1;
|
|
570
|
+
}
|
|
571
|
+
function resolveCircleLineWidth(squareSize, lineWidth) {
|
|
572
|
+
const candidate = lineWidth ?? squareSize * 0.08;
|
|
573
|
+
return Math.max(2, Math.min(8, candidate));
|
|
574
|
+
}
|
|
575
|
+
function resolveCircleRadius(squareSize, radius, lineWidth) {
|
|
576
|
+
const radiusPx = squareSize * (radius ?? 0.42);
|
|
577
|
+
return Math.max(0, radiusPx - lineWidth / 2);
|
|
578
|
+
}
|
|
515
579
|
function resolveBorderCoordinateFontSize(context, geometry) {
|
|
516
580
|
const maxFontSize = Math.floor(
|
|
517
581
|
Math.min(geometry.squareSize * 0.6, geometry.borderSize * 0.65)
|
|
@@ -608,6 +672,98 @@ function drawCoordinates(context, request, geometry) {
|
|
|
608
672
|
}
|
|
609
673
|
drawInsideCoordinates(context, request, geometry);
|
|
610
674
|
}
|
|
675
|
+
function drawBoardSquares(context, request, geometry) {
|
|
676
|
+
for (const square of SQUARES) {
|
|
677
|
+
const squareGeometry = geometry.squares[square];
|
|
678
|
+
context.fillStyle = isDarkSquare(square) ? request.colors.darkSquare : request.colors.lightSquare;
|
|
679
|
+
context.fillRect(
|
|
680
|
+
squareGeometry.x,
|
|
681
|
+
squareGeometry.y,
|
|
682
|
+
squareGeometry.size,
|
|
683
|
+
squareGeometry.size
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function drawFillHighlights(context, request, geometry) {
|
|
688
|
+
for (const highlight of request.highlights) {
|
|
689
|
+
if (highlight.style !== "fill") {
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
const squareGeometry = geometry.squares[highlight.square];
|
|
693
|
+
context.save();
|
|
694
|
+
context.globalAlpha = resolveHighlightOpacity(
|
|
695
|
+
highlight.style,
|
|
696
|
+
highlight.color,
|
|
697
|
+
highlight.opacity
|
|
698
|
+
);
|
|
699
|
+
context.fillStyle = highlight.color ?? request.colors.highlight;
|
|
700
|
+
context.fillRect(
|
|
701
|
+
squareGeometry.x,
|
|
702
|
+
squareGeometry.y,
|
|
703
|
+
squareGeometry.size,
|
|
704
|
+
squareGeometry.size
|
|
705
|
+
);
|
|
706
|
+
context.restore();
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
function drawCircleHighlights(context, request, geometry) {
|
|
710
|
+
for (const highlight of request.highlights) {
|
|
711
|
+
if (highlight.style !== "circle") {
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
const squareGeometry = geometry.squares[highlight.square];
|
|
715
|
+
const centerX = squareGeometry.x + squareGeometry.size / 2;
|
|
716
|
+
const centerY = squareGeometry.y + squareGeometry.size / 2;
|
|
717
|
+
context.save();
|
|
718
|
+
context.globalAlpha = resolveHighlightOpacity(
|
|
719
|
+
highlight.style,
|
|
720
|
+
highlight.color,
|
|
721
|
+
highlight.opacity
|
|
722
|
+
);
|
|
723
|
+
context.strokeStyle = highlight.color ?? "#ffcc00";
|
|
724
|
+
context.lineWidth = resolveCircleLineWidth(
|
|
725
|
+
squareGeometry.size,
|
|
726
|
+
highlight.lineWidth
|
|
727
|
+
);
|
|
728
|
+
const radius = resolveCircleRadius(
|
|
729
|
+
squareGeometry.size,
|
|
730
|
+
highlight.radius,
|
|
731
|
+
context.lineWidth
|
|
732
|
+
);
|
|
733
|
+
context.beginPath();
|
|
734
|
+
context.arc(
|
|
735
|
+
centerX,
|
|
736
|
+
centerY,
|
|
737
|
+
radius,
|
|
738
|
+
0,
|
|
739
|
+
Math.PI * 2
|
|
740
|
+
);
|
|
741
|
+
context.stroke();
|
|
742
|
+
context.restore();
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
async function drawPieces(context, request, geometry) {
|
|
746
|
+
for (const square of SQUARES) {
|
|
747
|
+
const squareGeometry = geometry.squares[square];
|
|
748
|
+
const pieceKey = request.board.squares[square];
|
|
749
|
+
if (!pieceKey) {
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
const raster = await getPieceRaster(
|
|
753
|
+
request.theme.name,
|
|
754
|
+
pieceKey,
|
|
755
|
+
request.theme.pieces[pieceKey],
|
|
756
|
+
Math.round(geometry.squareSize)
|
|
757
|
+
);
|
|
758
|
+
context.drawImage(
|
|
759
|
+
raster,
|
|
760
|
+
squareGeometry.x,
|
|
761
|
+
squareGeometry.y,
|
|
762
|
+
squareGeometry.size,
|
|
763
|
+
squareGeometry.size
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
611
767
|
var CanvasPngRenderer = class {
|
|
612
768
|
async render(request) {
|
|
613
769
|
try {
|
|
@@ -621,43 +777,11 @@ var CanvasPngRenderer = class {
|
|
|
621
777
|
const context = canvas.getContext("2d");
|
|
622
778
|
context.fillStyle = request.colors.lightSquare;
|
|
623
779
|
context.fillRect(0, 0, geometry.imageWidth, geometry.imageHeight);
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
context.fillRect(
|
|
628
|
-
squareGeometry.x,
|
|
629
|
-
squareGeometry.y,
|
|
630
|
-
squareGeometry.size,
|
|
631
|
-
squareGeometry.size
|
|
632
|
-
);
|
|
633
|
-
if (request.highlights.includes(square)) {
|
|
634
|
-
context.fillStyle = request.colors.highlight;
|
|
635
|
-
context.fillRect(
|
|
636
|
-
squareGeometry.x,
|
|
637
|
-
squareGeometry.y,
|
|
638
|
-
squareGeometry.size,
|
|
639
|
-
squareGeometry.size
|
|
640
|
-
);
|
|
641
|
-
}
|
|
642
|
-
const pieceKey = request.board.squares[square];
|
|
643
|
-
if (!pieceKey) {
|
|
644
|
-
continue;
|
|
645
|
-
}
|
|
646
|
-
const raster = await getPieceRaster(
|
|
647
|
-
request.theme.name,
|
|
648
|
-
pieceKey,
|
|
649
|
-
request.theme.pieces[pieceKey],
|
|
650
|
-
Math.round(geometry.squareSize)
|
|
651
|
-
);
|
|
652
|
-
context.drawImage(
|
|
653
|
-
raster,
|
|
654
|
-
squareGeometry.x,
|
|
655
|
-
squareGeometry.y,
|
|
656
|
-
squareGeometry.size,
|
|
657
|
-
squareGeometry.size
|
|
658
|
-
);
|
|
659
|
-
}
|
|
780
|
+
drawBoardSquares(context, request, geometry);
|
|
781
|
+
drawFillHighlights(context, request, geometry);
|
|
782
|
+
drawCircleHighlights(context, request, geometry);
|
|
660
783
|
drawCoordinates(context, request, geometry);
|
|
784
|
+
await drawPieces(context, request, geometry);
|
|
661
785
|
return canvas.toBuffer("image/png");
|
|
662
786
|
} catch (error) {
|
|
663
787
|
if (error instanceof RenderError) {
|
|
@@ -678,6 +802,31 @@ async function writeBufferToFile(filePath, buffer) {
|
|
|
678
802
|
}
|
|
679
803
|
}
|
|
680
804
|
|
|
805
|
+
// src/core/highlights.ts
|
|
806
|
+
function normalizeHighlightEntries(input) {
|
|
807
|
+
return input.map((entry) => {
|
|
808
|
+
if (typeof entry === "string") {
|
|
809
|
+
return {
|
|
810
|
+
square: validateSquare(entry),
|
|
811
|
+
style: "fill",
|
|
812
|
+
color: void 0,
|
|
813
|
+
opacity: void 0,
|
|
814
|
+
lineWidth: void 0,
|
|
815
|
+
radius: void 0
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
const style = entry.style ?? "fill";
|
|
819
|
+
return {
|
|
820
|
+
square: validateSquare(entry.square),
|
|
821
|
+
style,
|
|
822
|
+
color: entry.color ?? (style === "circle" ? "#ffcc00" : void 0),
|
|
823
|
+
opacity: entry.opacity ?? (style === "circle" ? 0.9 : void 0),
|
|
824
|
+
lineWidth: entry.lineWidth,
|
|
825
|
+
radius: style === "circle" ? entry.radius ?? 0.42 : void 0
|
|
826
|
+
};
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
|
|
681
830
|
// src/themes/builtins.ts
|
|
682
831
|
var import_node_fs = require("fs");
|
|
683
832
|
var import_node_path = require("path");
|
|
@@ -863,6 +1012,9 @@ function normalizeCoordinates(coordinates, borderSize) {
|
|
|
863
1012
|
color: coordinates.color ?? (position === "border" ? "#333" : void 0)
|
|
864
1013
|
};
|
|
865
1014
|
}
|
|
1015
|
+
function normalizeHighlightEntries2(highlights) {
|
|
1016
|
+
return normalizeHighlightEntries(highlights ?? []);
|
|
1017
|
+
}
|
|
866
1018
|
function normalizeRenderInputs(options) {
|
|
867
1019
|
const size = validateSize(options.size ?? DEFAULT_SIZE);
|
|
868
1020
|
const borderSize = validateBorderSize(
|
|
@@ -871,6 +1023,8 @@ function normalizeRenderInputs(options) {
|
|
|
871
1023
|
);
|
|
872
1024
|
validateBoardColors(options.colors);
|
|
873
1025
|
validateCoordinatesOption(options.coordinates, borderSize);
|
|
1026
|
+
validateHighlightsInput(options.highlights, options.highlightSquares);
|
|
1027
|
+
const highlightInput = options.highlights ?? options.highlightSquares;
|
|
874
1028
|
return {
|
|
875
1029
|
size,
|
|
876
1030
|
padding: normalizePadding(options.padding ?? DEFAULT_PADDING),
|
|
@@ -880,7 +1034,7 @@ function normalizeRenderInputs(options) {
|
|
|
880
1034
|
theme: options.theme,
|
|
881
1035
|
style: options.style
|
|
882
1036
|
}),
|
|
883
|
-
|
|
1037
|
+
highlights: normalizeHighlightEntries2(highlightInput),
|
|
884
1038
|
colors: normalizeColors(options.colors),
|
|
885
1039
|
coordinates: normalizeCoordinates(options.coordinates, borderSize)
|
|
886
1040
|
};
|
|
@@ -893,10 +1047,7 @@ var ChessImageGenerator = class {
|
|
|
893
1047
|
highlights = [];
|
|
894
1048
|
constructor(options = {}) {
|
|
895
1049
|
this.defaults = { ...options };
|
|
896
|
-
normalizeRenderInputs(
|
|
897
|
-
...this.defaults,
|
|
898
|
-
highlightSquares: []
|
|
899
|
-
});
|
|
1050
|
+
normalizeRenderInputs(this.defaults);
|
|
900
1051
|
}
|
|
901
1052
|
async loadFEN(fen) {
|
|
902
1053
|
this.position = parseFEN(fen);
|
|
@@ -910,8 +1061,9 @@ var ChessImageGenerator = class {
|
|
|
910
1061
|
this.position = parseBoardArray(board);
|
|
911
1062
|
this.clearHighlights();
|
|
912
1063
|
}
|
|
913
|
-
setHighlights(
|
|
914
|
-
|
|
1064
|
+
setHighlights(highlights) {
|
|
1065
|
+
validateHighlightsInput(highlights, void 0);
|
|
1066
|
+
this.highlights = [...highlights];
|
|
915
1067
|
}
|
|
916
1068
|
clearHighlights() {
|
|
917
1069
|
this.highlights = [];
|
|
@@ -923,12 +1075,13 @@ var ChessImageGenerator = class {
|
|
|
923
1075
|
const renderer = new CanvasPngRenderer();
|
|
924
1076
|
const normalized = normalizeRenderInputs({
|
|
925
1077
|
...this.defaults,
|
|
926
|
-
|
|
1078
|
+
highlights: this.highlights,
|
|
1079
|
+
highlightSquares: void 0
|
|
927
1080
|
});
|
|
928
1081
|
return renderer.render({
|
|
929
1082
|
board: this.position,
|
|
930
1083
|
theme: normalized.theme,
|
|
931
|
-
highlights: normalized.
|
|
1084
|
+
highlights: normalized.highlights,
|
|
932
1085
|
size: normalized.size,
|
|
933
1086
|
padding: normalized.padding,
|
|
934
1087
|
borderSize: normalized.borderSize,
|
|
@@ -971,7 +1124,7 @@ async function renderChess(options) {
|
|
|
971
1124
|
return renderer.render({
|
|
972
1125
|
board: position,
|
|
973
1126
|
theme: normalized.theme,
|
|
974
|
-
highlights: normalized.
|
|
1127
|
+
highlights: normalized.highlights,
|
|
975
1128
|
size: normalized.size,
|
|
976
1129
|
padding: normalized.padding,
|
|
977
1130
|
borderSize: normalized.borderSize,
|