From fb221ec408b45cd8defe199ed0863cb72292e3c5 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 16:13:09 +0900 Subject: [PATCH 01/19] =?UTF-8?q?=E4=BD=95=E3=82=82=E8=80=83=E3=81=88?= =?UTF-8?q?=E3=81=9A=E3=81=AB=E3=81=BE=E3=81=9A=E3=81=AFcomponent=E5=8D=98?= =?UTF-8?q?=E4=BD=8D=E3=81=A7=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92?= =?UTF-8?q?=E5=88=86=E3=81=91=E3=81=A6hooks=E3=81=AB=E7=BD=AE=E3=81=8D?= =?UTF-8?q?=E6=8F=9B=E3=81=88=E3=81=A6=E3=81=BF=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/board/index.tsx | 32 ++++ tic-tac-toe-app/src/components/game/index.tsx | 92 +++++++++++ .../src/components/square/index.tsx | 13 ++ tic-tac-toe-app/src/index.tsx | 152 +----------------- 4 files changed, 138 insertions(+), 151 deletions(-) create mode 100644 tic-tac-toe-app/src/components/board/index.tsx create mode 100644 tic-tac-toe-app/src/components/game/index.tsx create mode 100644 tic-tac-toe-app/src/components/square/index.tsx diff --git a/tic-tac-toe-app/src/components/board/index.tsx b/tic-tac-toe-app/src/components/board/index.tsx new file mode 100644 index 0000000..88d83a5 --- /dev/null +++ b/tic-tac-toe-app/src/components/board/index.tsx @@ -0,0 +1,32 @@ +import { Square, SquareValue } from "../square"; + +type BoardProps = { + squares: SquareValue[]; + onClick: (i: number) => void; +}; + +export const Board = (props: BoardProps) => { + function renderSquare(i: number) { + return props.onClick(i)} />; + } + + return ( +
+
+ {renderSquare(0)} + {renderSquare(1)} + {renderSquare(2)} +
+
+ {renderSquare(3)} + {renderSquare(4)} + {renderSquare(5)} +
+
+ {renderSquare(6)} + {renderSquare(7)} + {renderSquare(8)} +
+
+ ); +}; diff --git a/tic-tac-toe-app/src/components/game/index.tsx b/tic-tac-toe-app/src/components/game/index.tsx new file mode 100644 index 0000000..163c82a --- /dev/null +++ b/tic-tac-toe-app/src/components/game/index.tsx @@ -0,0 +1,92 @@ +import { useState } from "react"; +import { Board } from "../board"; +import { SquareValue } from "../square"; + +type GameHistory = { + squares: SquareValue[]; +}; + +const initialHistory: GameHistory[] = [ + { + squares: Array(9).fill(null), + }, +]; + +export const Game = () => { + const [history, setHistory] = useState(initialHistory); + const [stepNumber, setStepNumber] = useState(0); + const [xIsNext, setXIsNext] = useState(true); + + function handleClick(i: number) { + setHistory(history.slice(0, stepNumber + 1)); + const current = history[stepNumber]; + const squares = current.squares.slice(); + if (calculateWinner(squares) || squares[i]) { + return; + } + squares[i] = xIsNext ? "X" : "O"; + + setHistory( + history.concat([ + { + squares: squares, + }, + ]) + ); + setStepNumber(history.length); + setXIsNext(!xIsNext); + } + + function jumpTo(step: number) { + setStepNumber(step); + setXIsNext(step % 2 === 0); + } + + const current = history[stepNumber]; + const winner = calculateWinner(current.squares); + let statusMessage; + if (winner) { + statusMessage = "Winner: " + winner; + } else { + statusMessage = "Next player: " + (xIsNext ? "X" : "O"); + } + const moves = history.map((_, move) => { + const desc = move ? "Go to move #" + move : "Go to game start"; + return ( +
  • + +
  • + ); + }); + return ( +
    +
    + handleClick(i)} /> +
    +
    +
    {statusMessage}
    +
      {moves}
    +
    +
    + ); +}; + +function calculateWinner(squares: Array) { + const lines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ]; + for (let i = 0; i < lines.length; i++) { + const [a, b, c] = lines[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { + return squares[a]; + } + } + return null; +} diff --git a/tic-tac-toe-app/src/components/square/index.tsx b/tic-tac-toe-app/src/components/square/index.tsx new file mode 100644 index 0000000..0b1f577 --- /dev/null +++ b/tic-tac-toe-app/src/components/square/index.tsx @@ -0,0 +1,13 @@ +export type SquareValue = "X" | "O" | null; +type SquareProps = { + value: SquareValue; + onClick: () => void; +}; + +export const Square = (props: SquareProps) => { + return ( + + ); +}; diff --git a/tic-tac-toe-app/src/index.tsx b/tic-tac-toe-app/src/index.tsx index e02db4a..a1d6d44 100644 --- a/tic-tac-toe-app/src/index.tsx +++ b/tic-tac-toe-app/src/index.tsx @@ -2,157 +2,7 @@ import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import reportWebVitals from "./reportWebVitals"; - -type SquareValue = "X" | "O" | null; -type SquareProps = { - value: SquareValue; - onClick: () => void; -}; -function Square(props: SquareProps) { - return ( - - ); -} - -type BoardProps = { - squares: SquareValue[]; - onClick: (i: number) => void; -}; -class Board extends React.Component { - renderSquare(i: number) { - return ( - this.props.onClick(i)} - /> - ); - } - - render() { - return ( -
    -
    - {this.renderSquare(0)} - {this.renderSquare(1)} - {this.renderSquare(2)} -
    -
    - {this.renderSquare(3)} - {this.renderSquare(4)} - {this.renderSquare(5)} -
    -
    - {this.renderSquare(6)} - {this.renderSquare(7)} - {this.renderSquare(8)} -
    -
    - ); - } -} -type GameHistory = { - squares: SquareValue[]; -}; -type GameProps = {}; -type GameState = { - history: GameHistory[]; - stepNumber: number; - xIsNext: boolean; -}; -class Game extends React.Component { - constructor(props: GameProps) { - super(props); - this.state = { - history: [ - { - squares: Array(9).fill(null), - }, - ], - stepNumber: 0, - xIsNext: true, - }; - } - handleClick(i: number) { - const history = this.state.history.slice(0, this.state.stepNumber + 1); - const current = history[this.state.stepNumber]; - const squares = current.squares.slice(); - if (calculateWinner(squares) || squares[i]) { - return; - } - squares[i] = this.state.xIsNext ? "X" : "O"; - this.setState({ - history: history.concat([ - { - squares: squares, - }, - ]), - stepNumber: history.length, - xIsNext: !this.state.xIsNext, - }); - } - jumpTo(step: number) { - this.setState({ - stepNumber: step, - xIsNext: step % 2 === 0, - }); - } - render() { - const history = this.state.history; - const current = history[this.state.stepNumber]; - const winner = calculateWinner(current.squares); - let status; - if (winner) { - status = "Winner: " + winner; - } else { - status = "Next player: " + (this.state.xIsNext ? "X" : "O"); - } - const moves = history.map((_, move) => { - const desc = move ? "Go to move #" + move : "Go to game start"; - return ( -
  • - -
  • - ); - }); - return ( -
    -
    - this.handleClick(i)} - /> -
    -
    -
    {status}
    -
      {moves}
    -
    -
    - ); - } -} - -function calculateWinner(squares: Array) { - const lines = [ - [0, 1, 2], - [3, 4, 5], - [6, 7, 8], - [0, 3, 6], - [1, 4, 7], - [2, 5, 8], - [0, 4, 8], - [2, 4, 6], - ]; - for (let i = 0; i < lines.length; i++) { - const [a, b, c] = lines[i]; - if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { - return squares[a]; - } - } - return null; -} - +import { Game } from "./components/game"; // ======================================== ReactDOM.render(, document.getElementById("root")); From 314c49de658af6e918c2cc23c346b80c91f67a8f Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 17:26:21 +0900 Subject: [PATCH 02/19] =?UTF-8?q?=E9=9B=91=E3=81=ABeslint=E3=82=92?= =?UTF-8?q?=E5=B0=8E=E5=85=A5=E3=81=97=E3=81=A6=E3=81=BF=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tic-tac-toe-app/.eslintrc.js | 27 ++ tic-tac-toe-app/package-lock.json | 626 ++++++++++++++++++++++++++---- tic-tac-toe-app/package.json | 7 + 3 files changed, 588 insertions(+), 72 deletions(-) create mode 100644 tic-tac-toe-app/.eslintrc.js diff --git a/tic-tac-toe-app/.eslintrc.js b/tic-tac-toe-app/.eslintrc.js new file mode 100644 index 0000000..d04b87f --- /dev/null +++ b/tic-tac-toe-app/.eslintrc.js @@ -0,0 +1,27 @@ +module.exports = { + 'env': { + 'browser': true, + 'es2021': true, + }, + 'extends': [ + 'plugin:react/recommended', + 'google', + ], + 'parser': '@typescript-eslint/parser', + 'parserOptions': { + 'ecmaFeatures': { + 'jsx': true, + }, + 'ecmaVersion': 12, + 'sourceType': 'module', + }, + 'plugins': [ + 'react', + "react-hooks", + '@typescript-eslint', + ], + 'rules': { + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "warn", + }, +}; diff --git a/tic-tac-toe-app/package-lock.json b/tic-tac-toe-app/package-lock.json index d9b240d..a62002a 100644 --- a/tic-tac-toe-app/package-lock.json +++ b/tic-tac-toe-app/package-lock.json @@ -22,6 +22,13 @@ "web-vitals": "^1.1.2" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "eslint": "^7.32.0", + "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", "prettier": "2.5.0" } }, @@ -3667,29 +3674,111 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", + "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", + "devOptional": true, "dependencies": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", + "@typescript-eslint/experimental-utils": "5.5.0", + "@typescript-eslint/scope-manager": "5.5.0", + "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", - "regexpp": "^3.1.0", + "regexpp": "^3.2.0", "semver": "^7.3.5", "tsutils": "^3.21.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/experimental-utils": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", + "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", + "devOptional": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.5.0", + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/typescript-estree": "5.5.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", + "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", + "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", + "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { "typescript": { @@ -3697,10 +3786,37 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", + "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "devOptional": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -3735,24 +3851,25 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", + "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", + "devOptional": true, "dependencies": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" + "@typescript-eslint/scope-manager": "5.5.0", + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/typescript-estree": "5.5.0", + "debug": "^4.3.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -3760,6 +3877,104 @@ } } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", + "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", + "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", + "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", + "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", + "devOptional": true, + "dependencies": { + "@typescript-eslint/types": "5.5.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "devOptional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", @@ -7651,36 +7866,28 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-react-app": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", - "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", - "dependencies": { - "confusing-browser-globals": "^1.0.10" - }, + "node_modules/eslint-config-google": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", + "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "dev": true, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.10.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0", - "@typescript-eslint/parser": "^4.0.0", - "babel-eslint": "^10.0.0", - "eslint": "^7.5.0", - "eslint-plugin-flowtype": "^5.2.0", - "eslint-plugin-import": "^2.22.0", - "eslint-plugin-jest": "^24.0.0", - "eslint-plugin-jsx-a11y": "^6.3.1", - "eslint-plugin-react": "^7.20.3", - "eslint-plugin-react-hooks": "^4.0.8", - "eslint-plugin-testing-library": "^3.9.0" + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "peerDependenciesMeta": { - "eslint-plugin-jest": { - "optional": true - }, - "eslint-plugin-testing-library": { - "optional": true - } + "peerDependencies": { + "eslint": ">=7.0.0" } }, "node_modules/eslint-import-resolver-node": { @@ -16329,6 +16536,109 @@ "semver": "bin/semver" } }, + "node_modules/react-scripts/node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dependencies": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scripts/node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-scripts/node_modules/@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dependencies": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scripts/node_modules/eslint-config-react-app": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", + "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", + "dependencies": { + "confusing-browser-globals": "^1.0.10" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0", + "@typescript-eslint/parser": "^4.0.0", + "babel-eslint": "^10.0.0", + "eslint": "^7.5.0", + "eslint-plugin-flowtype": "^5.2.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-jest": "^24.0.0", + "eslint-plugin-jsx-a11y": "^6.3.1", + "eslint-plugin-react": "^7.20.3", + "eslint-plugin-react-hooks": "^4.0.8", + "eslint-plugin-testing-library": "^3.9.0" + }, + "peerDependenciesMeta": { + "eslint-plugin-jest": { + "optional": true + }, + "eslint-plugin-testing-library": { + "optional": true + } + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -18594,9 +18904,9 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/table": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", - "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", + "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -24097,24 +24407,87 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", + "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", + "devOptional": true, "requires": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", + "@typescript-eslint/experimental-utils": "5.5.0", + "@typescript-eslint/scope-manager": "5.5.0", + "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", - "regexpp": "^3.1.0", + "regexpp": "^3.2.0", "semver": "^7.3.5", "tsutils": "^3.21.0" }, "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", + "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", + "devOptional": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.5.0", + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/typescript-estree": "5.5.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", + "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0" + } + }, + "@typescript-eslint/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", + "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", + "devOptional": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", + "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", + "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "eslint-visitor-keys": "^3.0.0" + } + }, + "eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "devOptional": true + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "devOptional": true, "requires": { "lru-cache": "^6.0.0" } @@ -24135,14 +24508,73 @@ } }, "@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", + "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", + "devOptional": true, "requires": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" + "@typescript-eslint/scope-manager": "5.5.0", + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/typescript-estree": "5.5.0", + "debug": "^4.3.2" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", + "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0" + } + }, + "@typescript-eslint/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", + "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", + "devOptional": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", + "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "@typescript-eslint/visitor-keys": "5.5.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", + "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", + "devOptional": true, + "requires": { + "@typescript-eslint/types": "5.5.0", + "eslint-visitor-keys": "^3.0.0" + } + }, + "eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "devOptional": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "devOptional": true, + "requires": { + "lru-cache": "^6.0.0" + } + } } }, "@typescript-eslint/scope-manager": { @@ -27337,13 +27769,19 @@ } } }, - "eslint-config-react-app": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", - "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", - "requires": { - "confusing-browser-globals": "^1.0.10" - } + "eslint-config-google": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", + "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "dev": true, + "requires": {} + }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.6", @@ -33855,6 +34293,50 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "requires": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "requires": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + } + }, + "eslint-config-react-app": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", + "integrity": "sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==", + "requires": { + "confusing-browser-globals": "^1.0.10" + } } } }, @@ -35673,9 +36155,9 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "table": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", - "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", + "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", "requires": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", diff --git a/tic-tac-toe-app/package.json b/tic-tac-toe-app/package.json index ba77538..ab98dbd 100644 --- a/tic-tac-toe-app/package.json +++ b/tic-tac-toe-app/package.json @@ -41,6 +41,13 @@ ] }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "eslint": "^7.32.0", + "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", "prettier": "2.5.0" } } From 566104035c420d57053659a90e8477cbf4745a14 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 18:26:56 +0900 Subject: [PATCH 03/19] =?UTF-8?q?=E3=81=A1=E3=82=87=E3=81=A3=E3=81=A8?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E8=A6=8B=E7=9B=B4=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tic-tac-toe-app/.eslintrc.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tic-tac-toe-app/.eslintrc.js b/tic-tac-toe-app/.eslintrc.js index d04b87f..34b9f95 100644 --- a/tic-tac-toe-app/.eslintrc.js +++ b/tic-tac-toe-app/.eslintrc.js @@ -5,8 +5,15 @@ module.exports = { }, 'extends': [ 'plugin:react/recommended', + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", 'google', ], + 'globals': { + Atomics: "readonly", + SharedArrayBuffer: "readonly", + React: "writable", + }, 'parser': '@typescript-eslint/parser', 'parserOptions': { 'ecmaFeatures': { @@ -24,4 +31,5 @@ module.exports = { "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", }, + 'settings': { 'react': { 'version': "detect" } }, }; From 84437178295c17cf01d3e43718a58bdcde7ba393 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 18:27:09 +0900 Subject: [PATCH 04/19] apply eslint --- .../src/components/board/index.tsx | 6 +- tic-tac-toe-app/src/components/game/index.tsx | 72 +++++++++---------- .../src/components/square/index.tsx | 2 +- tic-tac-toe-app/src/index.tsx | 12 ++-- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/tic-tac-toe-app/src/components/board/index.tsx b/tic-tac-toe-app/src/components/board/index.tsx index 88d83a5..a298914 100644 --- a/tic-tac-toe-app/src/components/board/index.tsx +++ b/tic-tac-toe-app/src/components/board/index.tsx @@ -1,4 +1,4 @@ -import { Square, SquareValue } from "../square"; +import {Square, SquareValue} from '../square'; type BoardProps = { squares: SquareValue[]; @@ -6,9 +6,9 @@ type BoardProps = { }; export const Board = (props: BoardProps) => { - function renderSquare(i: number) { + const renderSquare = (i: number) => { return props.onClick(i)} />; - } + }; return (
    diff --git a/tic-tac-toe-app/src/components/game/index.tsx b/tic-tac-toe-app/src/components/game/index.tsx index 163c82a..9c4eb39 100644 --- a/tic-tac-toe-app/src/components/game/index.tsx +++ b/tic-tac-toe-app/src/components/game/index.tsx @@ -1,6 +1,6 @@ -import { useState } from "react"; -import { Board } from "../board"; -import { SquareValue } from "../square"; +import {useState} from 'react'; +import {Board} from '../board'; +import {SquareValue} from '../square'; type GameHistory = { squares: SquareValue[]; @@ -12,46 +12,66 @@ const initialHistory: GameHistory[] = [ }, ]; +const calculateWinner = (squares: Array) => { + const lines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ]; + for (let i = 0; i < lines.length; i++) { + const [a, b, c] = lines[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { + return squares[a]; + } + } + return null; +}; + export const Game = () => { const [history, setHistory] = useState(initialHistory); const [stepNumber, setStepNumber] = useState(0); const [xIsNext, setXIsNext] = useState(true); - function handleClick(i: number) { + const handleClick = (i: number) => { setHistory(history.slice(0, stepNumber + 1)); const current = history[stepNumber]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } - squares[i] = xIsNext ? "X" : "O"; + squares[i] = xIsNext ? 'X' : 'O'; setHistory( - history.concat([ - { - squares: squares, - }, - ]) + history.concat([ + { + squares: squares, + }, + ]), ); setStepNumber(history.length); setXIsNext(!xIsNext); - } + }; - function jumpTo(step: number) { + const jumpTo = (step: number) => { setStepNumber(step); setXIsNext(step % 2 === 0); - } + }; const current = history[stepNumber]; const winner = calculateWinner(current.squares); let statusMessage; if (winner) { - statusMessage = "Winner: " + winner; + statusMessage = 'Winner: ' + winner; } else { - statusMessage = "Next player: " + (xIsNext ? "X" : "O"); + statusMessage = 'Next player: ' + (xIsNext ? 'X' : 'O'); } const moves = history.map((_, move) => { - const desc = move ? "Go to move #" + move : "Go to game start"; + const desc = move ? 'Go to move #' + move : 'Go to game start'; return (
  • @@ -70,23 +90,3 @@ export const Game = () => {
  • ); }; - -function calculateWinner(squares: Array) { - const lines = [ - [0, 1, 2], - [3, 4, 5], - [6, 7, 8], - [0, 3, 6], - [1, 4, 7], - [2, 5, 8], - [0, 4, 8], - [2, 4, 6], - ]; - for (let i = 0; i < lines.length; i++) { - const [a, b, c] = lines[i]; - if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { - return squares[a]; - } - } - return null; -} diff --git a/tic-tac-toe-app/src/components/square/index.tsx b/tic-tac-toe-app/src/components/square/index.tsx index 0b1f577..079274b 100644 --- a/tic-tac-toe-app/src/components/square/index.tsx +++ b/tic-tac-toe-app/src/components/square/index.tsx @@ -1,4 +1,4 @@ -export type SquareValue = "X" | "O" | null; +export type SquareValue = 'X' | 'O' | null; type SquareProps = { value: SquareValue; onClick: () => void; diff --git a/tic-tac-toe-app/src/index.tsx b/tic-tac-toe-app/src/index.tsx index a1d6d44..8a9eb2e 100644 --- a/tic-tac-toe-app/src/index.tsx +++ b/tic-tac-toe-app/src/index.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import "./index.css"; -import reportWebVitals from "./reportWebVitals"; -import { Game } from "./components/game"; +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import reportWebVitals from './reportWebVitals'; +import {Game} from './components/game'; // ======================================== -ReactDOM.render(, document.getElementById("root")); +ReactDOM.render(, document.getElementById('root')); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) From dacf409c7a775ee123cb4cea1a8f4932bfc20eb5 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 18:29:44 +0900 Subject: [PATCH 05/19] =?UTF-8?q?=E3=81=A1=E3=82=87=E3=81=84=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tic-tac-toe-app/.eslintrc.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tic-tac-toe-app/.eslintrc.js b/tic-tac-toe-app/.eslintrc.js index 34b9f95..e5e8418 100644 --- a/tic-tac-toe-app/.eslintrc.js +++ b/tic-tac-toe-app/.eslintrc.js @@ -27,9 +27,6 @@ module.exports = { "react-hooks", '@typescript-eslint', ], - 'rules': { - "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "warn", - }, + 'rules': {}, 'settings': { 'react': { 'version': "detect" } }, }; From b1aa90661affc3b5992b3c0cce680ae0964422e4 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 20:39:08 +0900 Subject: [PATCH 06/19] eslit fix. --- tic-tac-toe-app/.eslintrc.js | 54 +++++++++++++------------- tic-tac-toe-app/src/reportWebVitals.ts | 4 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tic-tac-toe-app/.eslintrc.js b/tic-tac-toe-app/.eslintrc.js index e5e8418..fde0a99 100644 --- a/tic-tac-toe-app/.eslintrc.js +++ b/tic-tac-toe-app/.eslintrc.js @@ -1,32 +1,32 @@ module.exports = { - 'env': { - 'browser': true, - 'es2021': true, - }, - 'extends': [ - 'plugin:react/recommended', + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended", - 'google', - ], - 'globals': { - Atomics: "readonly", - SharedArrayBuffer: "readonly", - React: "writable", - }, - 'parser': '@typescript-eslint/parser', - 'parserOptions': { - 'ecmaFeatures': { - 'jsx': true, + "plugin:react/recommended", + ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly", + "React": "writable", + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": [ + "react", + "@typescript-eslint" + ], + "rules": { }, - 'ecmaVersion': 12, - 'sourceType': 'module', - }, - 'plugins': [ - 'react', - "react-hooks", - '@typescript-eslint', - ], - 'rules': {}, - 'settings': { 'react': { 'version': "detect" } }, + "settings": { "react": { "version": "detect" } }, }; diff --git a/tic-tac-toe-app/src/reportWebVitals.ts b/tic-tac-toe-app/src/reportWebVitals.ts index 49a2a16..b7876a4 100644 --- a/tic-tac-toe-app/src/reportWebVitals.ts +++ b/tic-tac-toe-app/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); From 28a34ff93232e8721fa28154084969bea9e69b86 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 20:39:29 +0900 Subject: [PATCH 07/19] =?UTF-8?q?component=E5=88=86=E5=89=B2=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=BF=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/game/GameHistoryButton.tsx | 14 +++++ .../game/GameHitstoryButtonList.tsx | 24 +++++++++ .../src/components/game/GameInfo.tsx | 27 ++++++++++ tic-tac-toe-app/src/components/game/index.tsx | 52 ++++++++----------- 4 files changed, 86 insertions(+), 31 deletions(-) create mode 100644 tic-tac-toe-app/src/components/game/GameHistoryButton.tsx create mode 100644 tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx create mode 100644 tic-tac-toe-app/src/components/game/GameInfo.tsx diff --git a/tic-tac-toe-app/src/components/game/GameHistoryButton.tsx b/tic-tac-toe-app/src/components/game/GameHistoryButton.tsx new file mode 100644 index 0000000..12f971a --- /dev/null +++ b/tic-tac-toe-app/src/components/game/GameHistoryButton.tsx @@ -0,0 +1,14 @@ +import { VFC } from "react"; + +type GameHistoryButtonProps = { + move: number; + onClick: (move: number) => void; +}; + +export const GameHistoryButton: VFC = ( + props: GameHistoryButtonProps +) => { + const desc = props.move ? "Go to move #" + props.move : "Go to game start"; + + return ; +}; diff --git a/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx b/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx new file mode 100644 index 0000000..a37a799 --- /dev/null +++ b/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx @@ -0,0 +1,24 @@ +import { VFC } from "react"; +import { GameHistory } from "./"; +import { GameHistoryButton } from "./GameHistoryButton"; + +type GameHistoryButtonListProps = { + history: GameHistory[]; + onClick: (move: number) => void; +}; + +export const GameHistoryButtonList: VFC = ( + props: GameHistoryButtonListProps +) => { + return ( +
      + {props.history.map((_, move) => { + return ( +
    1. + +
    2. + ); + })} +
    + ); +}; diff --git a/tic-tac-toe-app/src/components/game/GameInfo.tsx b/tic-tac-toe-app/src/components/game/GameInfo.tsx new file mode 100644 index 0000000..5f0866d --- /dev/null +++ b/tic-tac-toe-app/src/components/game/GameInfo.tsx @@ -0,0 +1,27 @@ +import { VFC } from "react"; +import { GameHistory } from "./"; +import { GameHistoryButtonList } from "./GameHitstoryButtonList"; + +type GameInfoProps = { + winner: string | null; + xIsNext: boolean; + history: GameHistory[]; + onClick: (move: number) => void; +}; + +export const GameInfo: VFC = (props: GameInfoProps) => { + const statusMessage = (winner: string | null, xIsNext: boolean) => { + if (props.winner) { + return "Winner: " + winner; + } else { + return "Next player: " + (xIsNext ? "X" : "O"); + } + }; + + return ( +
    +
    {statusMessage(props.winner, props.xIsNext)}
    + +
    + ); +}; diff --git a/tic-tac-toe-app/src/components/game/index.tsx b/tic-tac-toe-app/src/components/game/index.tsx index 9c4eb39..2e64dde 100644 --- a/tic-tac-toe-app/src/components/game/index.tsx +++ b/tic-tac-toe-app/src/components/game/index.tsx @@ -1,8 +1,9 @@ -import {useState} from 'react'; -import {Board} from '../board'; -import {SquareValue} from '../square'; +import { useState } from "react"; +import { Board } from "../board"; +import { SquareValue } from "../square"; +import { GameInfo } from "./GameInfo"; -type GameHistory = { +export type GameHistory = { squares: SquareValue[]; }; @@ -38,22 +39,22 @@ export const Game = () => { const [xIsNext, setXIsNext] = useState(true); const handleClick = (i: number) => { - setHistory(history.slice(0, stepNumber + 1)); - const current = history[stepNumber]; + const updatedHistory = history.slice(0, stepNumber + 1); + const current = updatedHistory[stepNumber]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } - squares[i] = xIsNext ? 'X' : 'O'; + squares[i] = xIsNext ? "X" : "O"; setHistory( - history.concat([ - { - squares: squares, - }, - ]), + updatedHistory.concat([ + { + squares: squares, + }, + ]) ); - setStepNumber(history.length); + setStepNumber(updatedHistory.length); setXIsNext(!xIsNext); }; @@ -64,29 +65,18 @@ export const Game = () => { const current = history[stepNumber]; const winner = calculateWinner(current.squares); - let statusMessage; - if (winner) { - statusMessage = 'Winner: ' + winner; - } else { - statusMessage = 'Next player: ' + (xIsNext ? 'X' : 'O'); - } - const moves = history.map((_, move) => { - const desc = move ? 'Go to move #' + move : 'Go to game start'; - return ( -
  • - -
  • - ); - }); + return (
    handleClick(i)} />
    -
    -
    {statusMessage}
    -
      {moves}
    -
    +
    ); }; From 4493c84547536a27d571498ad99051c14ebde461 Mon Sep 17 00:00:00 2001 From: ookura-mf Date: Mon, 6 Dec 2021 20:41:13 +0900 Subject: [PATCH 08/19] Add return type. --- tic-tac-toe-app/src/components/board/index.tsx | 5 +++-- tic-tac-toe-app/src/components/game/index.tsx | 4 ++-- tic-tac-toe-app/src/components/square/index.tsx | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tic-tac-toe-app/src/components/board/index.tsx b/tic-tac-toe-app/src/components/board/index.tsx index a298914..636422d 100644 --- a/tic-tac-toe-app/src/components/board/index.tsx +++ b/tic-tac-toe-app/src/components/board/index.tsx @@ -1,11 +1,12 @@ -import {Square, SquareValue} from '../square'; +import { VFC } from "react"; +import { Square, SquareValue } from "../square"; type BoardProps = { squares: SquareValue[]; onClick: (i: number) => void; }; -export const Board = (props: BoardProps) => { +export const Board: VFC = (props: BoardProps) => { const renderSquare = (i: number) => { return props.onClick(i)} />; }; diff --git a/tic-tac-toe-app/src/components/game/index.tsx b/tic-tac-toe-app/src/components/game/index.tsx index 2e64dde..f4161c3 100644 --- a/tic-tac-toe-app/src/components/game/index.tsx +++ b/tic-tac-toe-app/src/components/game/index.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, VFC } from "react"; import { Board } from "../board"; import { SquareValue } from "../square"; import { GameInfo } from "./GameInfo"; @@ -33,7 +33,7 @@ const calculateWinner = (squares: Array) => { return null; }; -export const Game = () => { +export const Game: VFC = () => { const [history, setHistory] = useState(initialHistory); const [stepNumber, setStepNumber] = useState(0); const [xIsNext, setXIsNext] = useState(true); diff --git a/tic-tac-toe-app/src/components/square/index.tsx b/tic-tac-toe-app/src/components/square/index.tsx index 079274b..41ae3e6 100644 --- a/tic-tac-toe-app/src/components/square/index.tsx +++ b/tic-tac-toe-app/src/components/square/index.tsx @@ -1,10 +1,12 @@ -export type SquareValue = 'X' | 'O' | null; +import { VFC } from "react"; + +export type SquareValue = "X" | "O" | null; type SquareProps = { value: SquareValue; onClick: () => void; }; -export const Square = (props: SquareProps) => { +export const Square: VFC = (props: SquareProps) => { return ( ; diff --git a/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx b/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx index a37a799..cd0ab8f 100644 --- a/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx +++ b/tic-tac-toe-app/src/components/game/GameHitstoryButtonList.tsx @@ -1,4 +1,3 @@ -import { VFC } from "react"; import { GameHistory } from "./"; import { GameHistoryButton } from "./GameHistoryButton"; @@ -7,9 +6,7 @@ type GameHistoryButtonListProps = { onClick: (move: number) => void; }; -export const GameHistoryButtonList: VFC = ( - props: GameHistoryButtonListProps -) => { +export const GameHistoryButtonList = (props: GameHistoryButtonListProps) => { return (
      {props.history.map((_, move) => { diff --git a/tic-tac-toe-app/src/components/game/GameInfo.tsx b/tic-tac-toe-app/src/components/game/GameInfo.tsx index 5f0866d..bbb4022 100644 --- a/tic-tac-toe-app/src/components/game/GameInfo.tsx +++ b/tic-tac-toe-app/src/components/game/GameInfo.tsx @@ -1,4 +1,3 @@ -import { VFC } from "react"; import { GameHistory } from "./"; import { GameHistoryButtonList } from "./GameHitstoryButtonList"; @@ -9,7 +8,7 @@ type GameInfoProps = { onClick: (move: number) => void; }; -export const GameInfo: VFC = (props: GameInfoProps) => { +export const GameInfo = (props: GameInfoProps) => { const statusMessage = (winner: string | null, xIsNext: boolean) => { if (props.winner) { return "Winner: " + winner; diff --git a/tic-tac-toe-app/src/components/game/index.tsx b/tic-tac-toe-app/src/components/game/index.tsx index f4161c3..2e64dde 100644 --- a/tic-tac-toe-app/src/components/game/index.tsx +++ b/tic-tac-toe-app/src/components/game/index.tsx @@ -1,4 +1,4 @@ -import { useState, VFC } from "react"; +import { useState } from "react"; import { Board } from "../board"; import { SquareValue } from "../square"; import { GameInfo } from "./GameInfo"; @@ -33,7 +33,7 @@ const calculateWinner = (squares: Array) => { return null; }; -export const Game: VFC = () => { +export const Game = () => { const [history, setHistory] = useState(initialHistory); const [stepNumber, setStepNumber] = useState(0); const [xIsNext, setXIsNext] = useState(true); diff --git a/tic-tac-toe-app/src/components/square/index.tsx b/tic-tac-toe-app/src/components/square/index.tsx index 41ae3e6..0b1f577 100644 --- a/tic-tac-toe-app/src/components/square/index.tsx +++ b/tic-tac-toe-app/src/components/square/index.tsx @@ -1,12 +1,10 @@ -import { VFC } from "react"; - export type SquareValue = "X" | "O" | null; type SquareProps = { value: SquareValue; onClick: () => void; }; -export const Square: VFC = (props: SquareProps) => { +export const Square = (props: SquareProps) => { return ( ); }; diff --git a/tic-tac-toe-app/src/reducers/gameReducer.ts b/tic-tac-toe-app/src/reducers/gameReducer.ts index 6545929..236d501 100644 --- a/tic-tac-toe-app/src/reducers/gameReducer.ts +++ b/tic-tac-toe-app/src/reducers/gameReducer.ts @@ -8,11 +8,11 @@ export type GameState = { xIsNext: boolean; }; export type GameAction = - | AddValueAction + | AddmarkAction | JumpHistoryAction -type AddValueAction = { - type: "add_value"; +type AddmarkAction = { + type: "add_mark"; squareIndex: number; } @@ -26,7 +26,7 @@ export const gameReducer: React.Reducer = ( action: GameAction ) => { switch (action.type) { - case "add_value": { + case "add_mark": { const updatedHistory = state.history.slice(0, state.stepNumber + 1); const current = updatedHistory[state.stepNumber]; const squares = current.squares.slice(); diff --git a/tic-tac-toe-app/src/usecases/CalculateWinner.ts b/tic-tac-toe-app/src/usecases/CalculateWinner.ts index 740e610..27e9edd 100644 --- a/tic-tac-toe-app/src/usecases/CalculateWinner.ts +++ b/tic-tac-toe-app/src/usecases/CalculateWinner.ts @@ -1,6 +1,6 @@ -import { SquareValue } from "../components/square/Square"; +import { Mark } from "../components/square/Square"; -export const calculateWinner = (squares: Array) => { +export const calculateWinner = (squares: Array) => { const lines = [ [0, 1, 2], [3, 4, 5],