diff --git a/.eslintignore b/.eslintignore index 0051b4b..0d67ec3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,5 @@ node_modules # don't lint build output (make sure it's set to your correct build folder name) dist +# Ignore eslintrc +.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 80e08d5..fca472f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,11 +1,6 @@ module.exports = { root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - ], + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint"], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], }; diff --git a/src/App.css b/src/App.css index 2c87728..d8cb6a0 100644 --- a/src/App.css +++ b/src/App.css @@ -42,10 +42,10 @@ body { } .chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n), -.chess-board tr:nth-child(2n+1) td.icon-cell:nth-child(2n+1) { +.chess-board tr:nth-child(2n + 1) td.icon-cell:nth-child(2n + 1) { background-color: #e5e5e5; } -.chess-board tr:nth-child(2n+1) td.icon-cell:nth-child(2n), -.chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n+1) { +.chess-board tr:nth-child(2n + 1) td.icon-cell:nth-child(2n), +.chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n + 1) { background-color: #c49d9d; } diff --git a/src/App.test.tsx b/src/App.test.tsx index 39d8256..f571dd0 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,5 +1,5 @@ -test('it works', () => { +test("it works", () => { expect(2 + 2).toEqual(4); -}) +}); -export { } +export {}; diff --git a/src/App.tsx b/src/App.tsx index 27f0cac..52ea82f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,9 @@ import Board, { BoardState } from "./Board"; -import './App.css'; +import "./App.css"; const App = (): JSX.Element => { const boardState: BoardState = { - "a": { + a: { 1: { kind: "king", color: "white", @@ -11,9 +11,9 @@ const App = (): JSX.Element => { 2: { kind: "pawn", color: "white", - } + }, }, - "b": { + b: { 1: { kind: "rook", color: "white", @@ -21,27 +21,32 @@ const App = (): JSX.Element => { 2: { kind: "pawn", color: "white", - } + }, }, - "c": { + c: { 2: { kind: "pawn", color: "white", - } + }, }, - "h": { + h: { 4: { kind: "pawn", color: "black", - } - } + }, + }, }; return (
- Promise.resolve()} onMovePiece={() => Promise.resolve()} /> + Promise.resolve()} + onMovePiece={() => Promise.resolve()} + />
); -} +}; export default App; diff --git a/src/Board.tsx b/src/Board.tsx index 9d2759e..37b9b30 100644 --- a/src/Board.tsx +++ b/src/Board.tsx @@ -8,20 +8,23 @@ type RANK = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8; type Coordinates = { rank: RANK; file: FILE; -} +}; type PieceState = { kind: PIECE; color: COLOR; -} +}; type Selected = { - piece: PieceState, - location: Coordinates, -} + piece: PieceState; + location: Coordinates; +}; type OnSelectPiece = (selected: Selected) => Promise; -type OnMovePiece = (selected: Selected, destination: Coordinates) => Promise; +type OnMovePiece = ( + selected: Selected, + destination: Coordinates +) => Promise; type OnSelectDestination = (destination: Coordinates) => Promise; interface BoardProps { @@ -36,34 +39,26 @@ interface CellProps { playerColor: COLOR; rank: RANK; file: FILE; - selected: Selected | null, + selected: Selected | null; onSelectPiece: OnSelectPiece; onSelectDestination: OnSelectDestination; } type FileState = { [key in RANK]?: PieceState; -} +}; export type BoardState = { [key in FILE]?: FileState; -} +}; -const RANKS: RANK[] = [ - 1, 2, 3, 4, 5, 6, 7, 8, -]; +const RANKS: RANK[] = [1, 2, 3, 4, 5, 6, 7, 8]; -const FILES: FILE[] = [ - "a", "b", "c", "d", "e", "f", "g", "h", -]; +const FILES: FILE[] = ["a", "b", "c", "d", "e", "f", "g", "h"]; -const PIECES: PIECE[] = [ - "pawn", "rook", "knight", "bishop", "queen", "king" -]; +const PIECES: PIECE[] = ["pawn", "rook", "knight", "bishop", "queen", "king"]; -const COLORS: COLOR[] = [ - "white", "black" -] +const COLORS: COLOR[] = ["white", "black"]; const iconFor = ({ kind, color }: PieceState): string => { switch (kind) { @@ -82,20 +77,28 @@ const iconFor = ({ kind, color }: PieceState): string => { } }; -const Cell = ({ boardState, playerColor, rank, file, selected, onSelectDestination, onSelectPiece }: CellProps): JSX.Element => { +const Cell = ({ + boardState, + playerColor, + rank, + file, + selected, + onSelectDestination, + onSelectPiece, +}: CellProps): JSX.Element => { const filed = boardState[file]; const onEmptyClick = async () => { return await onSelectDestination({ rank, file }); }; - if (typeof (filed) === "undefined") { + if (typeof filed === "undefined") { return ; } const piece = filed[rank]; - if (typeof (piece) === "undefined") { + if (typeof piece === "undefined") { return ; } @@ -113,18 +116,28 @@ const Cell = ({ boardState, playerColor, rank, file, selected, onSelectDestinati const maybeOnClick = piece.color === playerColor ? onClick : undefined; - const classNames = selected !== null - && selected.piece.kind === piece.kind - && selected.piece.color === piece.color - && selected.location.file === file - && selected.location.rank === rank - ? ["icon-cell", "selected"] - : ["icon-cell"]; + const classNames = + selected !== null && + selected.piece.kind === piece.kind && + selected.piece.color === piece.color && + selected.location.file === file && + selected.location.rank === rank + ? ["icon-cell", "selected"] + : ["icon-cell"]; - return {iconFor(piece)}; + return ( + + {iconFor(piece)} + + ); }; -const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, playerColor }: BoardProps): JSX.Element => { +const Board = ({ + boardState, + onMovePiece, + onSelectPiece: superOnSelectPiece, + playerColor, +}: BoardProps): JSX.Element => { const [selected, setSelected] = React.useState(null); const onSelectPiece: OnSelectPiece = async (selected) => { @@ -133,7 +146,9 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla return await superOnSelectPiece(selected); }; - const onSelectDestination = async (destination: Coordinates): Promise => { + const onSelectDestination = async ( + destination: Coordinates + ): Promise => { if (selected === null) { return; } @@ -193,6 +208,4 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla }; export default Board; -export { - PIECES, COLORS, FILES, RANKS, -}; +export { PIECES, COLORS, FILES, RANKS }; diff --git a/src/index.css b/src/index.css index ec2585e..4a1df4d 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/src/index.tsx b/src/index.tsx index ef2edf8..ad9cbbb 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,14 +1,14 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; ReactDOM.render( , - document.getElementById('root') + document.getElementById("root") ); // If you want to start measuring performance in your app, pass a function diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts index 49a2a16..5fa3583 100644 --- a/src/reportWebVitals.ts +++ b/src/reportWebVitals.ts @@ -1,8 +1,8 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals"; const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/src/setupTests.ts b/src/setupTests.ts index 8f2609b..1dd407a 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom"; diff --git a/src/validate.test.ts b/src/validate.test.ts index 7546bb5..a7a3093 100644 --- a/src/validate.test.ts +++ b/src/validate.test.ts @@ -1,31 +1,31 @@ -import { validateBoardState } from './validate'; +import { validateBoardState } from "./validate"; -test('validates valid states', () => { +test("validates valid states", () => { const inputs = [ { - "a": { + a: { 3: { kind: "king", color: "black", - } - } + }, + }, }, { - "b": { + b: { 5: { kind: "rook", color: "white", - } - } + }, + }, }, { - "c": { + c: { 8: { kind: "bishop", color: "black", - } + }, }, - "e": { + e: { 4: { kind: "pawn", color: "white", @@ -37,9 +37,9 @@ test('validates valid states', () => { 7: { kind: "queen", color: "black", - } - } - } + }, + }, + }, ]; inputs.map((input) => { @@ -49,32 +49,32 @@ test('validates valid states', () => { }); }); -test('does not validate invalid states', () => { +test("does not validate invalid states", () => { const inputs = [ { - "j": { + j: { 3: { kind: "king", color: "black", - } - } + }, + }, }, { - "b": { + b: { 9: { kind: "rook", color: "white", - } - } + }, + }, }, { - "c": { + c: { 8: { kind: "bishop", color: "black", - } + }, }, - "e": { + e: { 4: { kind: "pawn", color: "white", @@ -86,9 +86,9 @@ test('does not validate invalid states', () => { 7: { kind: "queen", color: "black", - } - } - } + }, + }, + }, ]; inputs.map((input) => { diff --git a/src/validate.ts b/src/validate.ts index dd55760..3c0eb9c 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -6,29 +6,29 @@ const FILES_AS_STRINGS: string[] = FILES.map((file) => file as string); const RANKS_AS_NUMBERS: number[] = RANKS.map((rank) => rank as number); const validateBoardState = (input: unknown): BoardState | null => { - if (typeof (input) !== "object" || Array.isArray(input) || input === null) { + if (typeof input !== "object" || Array.isArray(input) || input === null) { console.error("Input is not keyed object"); return null; } const hasInvalidShape = Object.entries(input).some(([file, ranks]) => { - if (typeof (file) !== "string") { + if (typeof file !== "string") { console.error("file is not string"); return true; } if (!FILES_AS_STRINGS.includes(file)) { - console.error("file is not included in valid files") + console.error("file is not included in valid files"); return true; } - if (typeof (ranks) !== "object" || Array.isArray(ranks) || ranks === null) { + if (typeof ranks !== "object" || Array.isArray(ranks) || ranks === null) { console.error("ranks is not a keyed object"); return true; } return Object.entries(ranks).some(([rank, pieces]) => { - if (typeof (rank) !== "string") { + if (typeof rank !== "string") { console.error("rank is not a string"); return true; } @@ -38,26 +38,36 @@ const validateBoardState = (input: unknown): BoardState | null => { return true; } - if (typeof (pieces) !== "object" || Array.isArray(pieces) || pieces === null) { + if ( + typeof pieces !== "object" || + Array.isArray(pieces) || + pieces === null + ) { console.error("piece state is not a keyed object"); return true; } return Object.entries(pieces).some(([key, value]) => { - if (typeof (key) !== "string") { + if (typeof key !== "string") { console.error("piece key is not a string"); return true; } if (!["kind", "color"].includes(key)) { - console.error("piece key is not included in valid keys") + console.error("piece key is not included in valid keys"); return true; } - if (key === "kind" && (typeof (value) !== "string" || !PIECES_AS_STRINGS.includes(value))) { + if ( + key === "kind" && + (typeof value !== "string" || !PIECES_AS_STRINGS.includes(value)) + ) { console.error("kind's value is not a string, or not a valid piece"); return true; - } else if (key === "color" && (typeof (value) !== "string" || !COLORS_AS_STRINGS.includes(value))) { + } else if ( + key === "color" && + (typeof value !== "string" || !COLORS_AS_STRINGS.includes(value)) + ) { console.error("colors' value is not a string, or not a valid color"); return true; } @@ -73,7 +83,5 @@ const validateBoardState = (input: unknown): BoardState | null => { return input as BoardState; }; - -export { - validateBoardState, -}; + +export { validateBoardState }; diff --git a/tsconfig.json b/tsconfig.json index a273b0c..9d379a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -20,7 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": [ - "src" - ] + "include": ["src"] }