Run prettier

This commit is contained in:
Aode (lion) 2021-12-30 10:31:23 -06:00
parent f417229526
commit 6ec72dd643
13 changed files with 141 additions and 124 deletions

View file

@ -2,3 +2,5 @@
node_modules node_modules
# don't lint build output (make sure it's set to your correct build folder name) # don't lint build output (make sure it's set to your correct build folder name)
dist dist
# Ignore eslintrc
.eslintrc.js

View file

@ -1,11 +1,6 @@
module.exports = { module.exports = {
root: true, root: true,
parser: '@typescript-eslint/parser', parser: "@typescript-eslint/parser",
plugins: [ plugins: ["@typescript-eslint"],
'@typescript-eslint', extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
}; };

View file

@ -1,5 +1,5 @@
test('it works', () => { test("it works", () => {
expect(2 + 2).toEqual(4); expect(2 + 2).toEqual(4);
}) });
export { } export {};

View file

@ -1,9 +1,9 @@
import Board, { BoardState } from "./Board"; import Board, { BoardState } from "./Board";
import './App.css'; import "./App.css";
const App = (): JSX.Element => { const App = (): JSX.Element => {
const boardState: BoardState = { const boardState: BoardState = {
"a": { a: {
1: { 1: {
kind: "king", kind: "king",
color: "white", color: "white",
@ -11,9 +11,9 @@ const App = (): JSX.Element => {
2: { 2: {
kind: "pawn", kind: "pawn",
color: "white", color: "white",
}
}, },
"b": { },
b: {
1: { 1: {
kind: "rook", kind: "rook",
color: "white", color: "white",
@ -21,27 +21,32 @@ const App = (): JSX.Element => {
2: { 2: {
kind: "pawn", kind: "pawn",
color: "white", color: "white",
}
}, },
"c": { },
c: {
2: { 2: {
kind: "pawn", kind: "pawn",
color: "white", color: "white",
}
}, },
"h": { },
h: {
4: { 4: {
kind: "pawn", kind: "pawn",
color: "black", color: "black",
} },
} },
}; };
return ( return (
<div className="App"> <div className="App">
<Board playerColor="white" boardState={boardState} onSelectPiece={() => Promise.resolve()} onMovePiece={() => Promise.resolve()} /> <Board
playerColor="white"
boardState={boardState}
onSelectPiece={() => Promise.resolve()}
onMovePiece={() => Promise.resolve()}
/>
</div> </div>
); );
} };
export default App; export default App;

View file

@ -8,20 +8,23 @@ type RANK = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
type Coordinates = { type Coordinates = {
rank: RANK; rank: RANK;
file: FILE; file: FILE;
} };
type PieceState = { type PieceState = {
kind: PIECE; kind: PIECE;
color: COLOR; color: COLOR;
} };
type Selected = { type Selected = {
piece: PieceState, piece: PieceState;
location: Coordinates, location: Coordinates;
} };
type OnSelectPiece = (selected: Selected) => Promise<void>; type OnSelectPiece = (selected: Selected) => Promise<void>;
type OnMovePiece = (selected: Selected, destination: Coordinates) => Promise<void>; type OnMovePiece = (
selected: Selected,
destination: Coordinates
) => Promise<void>;
type OnSelectDestination = (destination: Coordinates) => Promise<void>; type OnSelectDestination = (destination: Coordinates) => Promise<void>;
interface BoardProps { interface BoardProps {
@ -36,34 +39,26 @@ interface CellProps {
playerColor: COLOR; playerColor: COLOR;
rank: RANK; rank: RANK;
file: FILE; file: FILE;
selected: Selected | null, selected: Selected | null;
onSelectPiece: OnSelectPiece; onSelectPiece: OnSelectPiece;
onSelectDestination: OnSelectDestination; onSelectDestination: OnSelectDestination;
} }
type FileState = { type FileState = {
[key in RANK]?: PieceState; [key in RANK]?: PieceState;
} };
export type BoardState = { export type BoardState = {
[key in FILE]?: FileState; [key in FILE]?: FileState;
} };
const RANKS: RANK[] = [ const RANKS: RANK[] = [1, 2, 3, 4, 5, 6, 7, 8];
1, 2, 3, 4, 5, 6, 7, 8,
];
const FILES: FILE[] = [ const FILES: FILE[] = ["a", "b", "c", "d", "e", "f", "g", "h"];
"a", "b", "c", "d", "e", "f", "g", "h",
];
const PIECES: PIECE[] = [ const PIECES: PIECE[] = ["pawn", "rook", "knight", "bishop", "queen", "king"];
"pawn", "rook", "knight", "bishop", "queen", "king"
];
const COLORS: COLOR[] = [ const COLORS: COLOR[] = ["white", "black"];
"white", "black"
]
const iconFor = ({ kind, color }: PieceState): string => { const iconFor = ({ kind, color }: PieceState): string => {
switch (kind) { 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 filed = boardState[file];
const onEmptyClick = async () => { const onEmptyClick = async () => {
return await onSelectDestination({ rank, file }); return await onSelectDestination({ rank, file });
}; };
if (typeof (filed) === "undefined") { if (typeof filed === "undefined") {
return <td className="icon-cell" onClick={onEmptyClick}></td>; return <td className="icon-cell" onClick={onEmptyClick}></td>;
} }
const piece = filed[rank]; const piece = filed[rank];
if (typeof (piece) === "undefined") { if (typeof piece === "undefined") {
return <td className="icon-cell" onClick={onEmptyClick}></td>; return <td className="icon-cell" onClick={onEmptyClick}></td>;
} }
@ -113,18 +116,28 @@ const Cell = ({ boardState, playerColor, rank, file, selected, onSelectDestinati
const maybeOnClick = piece.color === playerColor ? onClick : undefined; const maybeOnClick = piece.color === playerColor ? onClick : undefined;
const classNames = selected !== null const classNames =
&& selected.piece.kind === piece.kind selected !== null &&
&& selected.piece.color === piece.color selected.piece.kind === piece.kind &&
&& selected.location.file === file selected.piece.color === piece.color &&
&& selected.location.rank === rank selected.location.file === file &&
selected.location.rank === rank
? ["icon-cell", "selected"] ? ["icon-cell", "selected"]
: ["icon-cell"]; : ["icon-cell"];
return <td className={classNames.join(" ")} onClick={maybeOnClick}><span className="icon">{iconFor(piece)}</span></td>; return (
<td className={classNames.join(" ")} onClick={maybeOnClick}>
<span className="icon">{iconFor(piece)}</span>
</td>
);
}; };
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<Selected | null>(null); const [selected, setSelected] = React.useState<Selected | null>(null);
const onSelectPiece: OnSelectPiece = async (selected) => { const onSelectPiece: OnSelectPiece = async (selected) => {
@ -133,7 +146,9 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla
return await superOnSelectPiece(selected); return await superOnSelectPiece(selected);
}; };
const onSelectDestination = async (destination: Coordinates): Promise<void> => { const onSelectDestination = async (
destination: Coordinates
): Promise<void> => {
if (selected === null) { if (selected === null) {
return; return;
} }
@ -193,6 +208,4 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla
}; };
export default Board; export default Board;
export { export { PIECES, COLORS, FILES, RANKS };
PIECES, COLORS, FILES, RANKS,
};

View file

@ -1,13 +1,13 @@
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif; sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
code { code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace; monospace;
} }

View file

@ -1,14 +1,14 @@
import React from 'react'; import React from "react";
import ReactDOM from 'react-dom'; import ReactDOM from "react-dom";
import './index.css'; import "./index.css";
import App from './App'; import App from "./App";
import reportWebVitals from './reportWebVitals'; import reportWebVitals from "./reportWebVitals";
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode>, </React.StrictMode>,
document.getElementById('root') document.getElementById("root")
); );
// If you want to start measuring performance in your app, pass a function // If you want to start measuring performance in your app, pass a function

View file

@ -1,8 +1,8 @@
import { ReportHandler } from 'web-vitals'; import { ReportHandler } from "web-vitals";
const reportWebVitals = (onPerfEntry?: ReportHandler) => { const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) { 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); getCLS(onPerfEntry);
getFID(onPerfEntry); getFID(onPerfEntry);
getFCP(onPerfEntry); getFCP(onPerfEntry);

View file

@ -2,4 +2,4 @@
// allows you to do things like: // allows you to do things like:
// expect(element).toHaveTextContent(/react/i) // expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom // learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom'; import "@testing-library/jest-dom";

View file

@ -1,31 +1,31 @@
import { validateBoardState } from './validate'; import { validateBoardState } from "./validate";
test('validates valid states', () => { test("validates valid states", () => {
const inputs = [ const inputs = [
{ {
"a": { a: {
3: { 3: {
kind: "king", kind: "king",
color: "black", color: "black",
} },
} },
}, },
{ {
"b": { b: {
5: { 5: {
kind: "rook", kind: "rook",
color: "white", color: "white",
} },
} },
}, },
{ {
"c": { c: {
8: { 8: {
kind: "bishop", kind: "bishop",
color: "black", color: "black",
}
}, },
"e": { },
e: {
4: { 4: {
kind: "pawn", kind: "pawn",
color: "white", color: "white",
@ -37,9 +37,9 @@ test('validates valid states', () => {
7: { 7: {
kind: "queen", kind: "queen",
color: "black", color: "black",
} },
} },
} },
]; ];
inputs.map((input) => { 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 = [ const inputs = [
{ {
"j": { j: {
3: { 3: {
kind: "king", kind: "king",
color: "black", color: "black",
} },
} },
}, },
{ {
"b": { b: {
9: { 9: {
kind: "rook", kind: "rook",
color: "white", color: "white",
} },
} },
}, },
{ {
"c": { c: {
8: { 8: {
kind: "bishop", kind: "bishop",
color: "black", color: "black",
}
}, },
"e": { },
e: {
4: { 4: {
kind: "pawn", kind: "pawn",
color: "white", color: "white",
@ -86,9 +86,9 @@ test('does not validate invalid states', () => {
7: { 7: {
kind: "queen", kind: "queen",
color: "black", color: "black",
} },
} },
} },
]; ];
inputs.map((input) => { inputs.map((input) => {

View file

@ -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 RANKS_AS_NUMBERS: number[] = RANKS.map((rank) => rank as number);
const validateBoardState = (input: unknown): BoardState | null => { 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"); console.error("Input is not keyed object");
return null; return null;
} }
const hasInvalidShape = Object.entries(input).some(([file, ranks]) => { const hasInvalidShape = Object.entries(input).some(([file, ranks]) => {
if (typeof (file) !== "string") { if (typeof file !== "string") {
console.error("file is not string"); console.error("file is not string");
return true; return true;
} }
if (!FILES_AS_STRINGS.includes(file)) { 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; 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"); console.error("ranks is not a keyed object");
return true; return true;
} }
return Object.entries(ranks).some(([rank, pieces]) => { return Object.entries(ranks).some(([rank, pieces]) => {
if (typeof (rank) !== "string") { if (typeof rank !== "string") {
console.error("rank is not a string"); console.error("rank is not a string");
return true; return true;
} }
@ -38,26 +38,36 @@ const validateBoardState = (input: unknown): BoardState | null => {
return true; 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"); console.error("piece state is not a keyed object");
return true; return true;
} }
return Object.entries(pieces).some(([key, value]) => { return Object.entries(pieces).some(([key, value]) => {
if (typeof (key) !== "string") { if (typeof key !== "string") {
console.error("piece key is not a string"); console.error("piece key is not a string");
return true; return true;
} }
if (!["kind", "color"].includes(key)) { 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; 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"); console.error("kind's value is not a string, or not a valid piece");
return true; 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"); console.error("colors' value is not a string, or not a valid color");
return true; return true;
} }
@ -74,6 +84,4 @@ const validateBoardState = (input: unknown): BoardState | null => {
return input as BoardState; return input as BoardState;
}; };
export { export { validateBoardState };
validateBoardState,
};

View file

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -20,7 +16,5 @@
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx"
}, },
"include": [ "include": ["src"]
"src"
]
} }