kokopu-react 1.7.2 → 1.8.0
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/CHANGELOG.md +10 -0
- package/dist/lib/Chessboard.js +21 -31
- package/dist/lib/ErrorBox.js +3 -1
- package/dist/lib/Movetext.js +24 -15
- package/dist/lib/i18n.js +2 -1
- package/dist/lib/impl/util.js +12 -0
- package/doc_src/demo/PageChessboardInteraction.js +9 -9
- package/doc_src/demo/PageChessboardMove.js +8 -8
- package/doc_src/demo/PageMovetextInteraction.js +2 -2
- package/graphic_test_src/02_chessboard_simple.js +2 -2
- package/graphic_test_src/03_chessboard_flipped.js +2 -2
- package/graphic_test_src/05_chessboard_move.js +2 -2
- package/graphic_test_src/12_movetext_simple.js +3 -3
- package/graphic_test_src/13_movetext_error.js +4 -3
- package/graphic_test_src/common/games.pgn +3 -3
- package/package.json +8 -8
- package/src/Chessboard.js +19 -23
- package/src/ErrorBox.js +2 -1
- package/src/Movetext.js +20 -16
- package/src/i18n.js +1 -0
- package/src/impl/util.js +8 -0
- package/test/7_movetext_graphic.js +1 -1
- package/test/references/13_movetext_error/0.png +0 -0
- package/test/references/13_movetext_error/1.png +0 -0
- package/test/references/13_movetext_error/2.png +0 -0
- package/test/references/13_movetext_error/3.png +0 -0
- package/test/references/13_movetext_error/4.png +0 -0
- package/test/references/14_movetext_html/0.png +0 -0
- package/test/references/14_movetext_html/1.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
ChangeLog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
1.8.0 (August 26, 2022)
|
|
5
|
+
-----------------------
|
|
6
|
+
* Upgrade Kokopu to Kokopu 3.0.
|
|
7
|
+
* Upgrade dependencies.
|
|
8
|
+
|
|
9
|
+
1.7.2 (August 3, 2022)
|
|
10
|
+
----------------------
|
|
11
|
+
* Fix URLs in documentation.
|
|
12
|
+
* Upgrade dependencies.
|
|
13
|
+
|
|
4
14
|
1.7.1 (June 23, 2022)
|
|
5
15
|
---------------------
|
|
6
16
|
* `React` and `kokopu` declared as peer dependencies.
|
package/dist/lib/Chessboard.js
CHANGED
|
@@ -13,7 +13,7 @@ var _reactDraggable = _interopRequireDefault(require("react-draggable"));
|
|
|
13
13
|
|
|
14
14
|
var _reactMotion = require("react-motion");
|
|
15
15
|
|
|
16
|
-
var _kokopu =
|
|
16
|
+
var _kokopu = require("kokopu");
|
|
17
17
|
|
|
18
18
|
var _colorsets2 = _interopRequireDefault(require("./impl/colorsets"));
|
|
19
19
|
|
|
@@ -161,12 +161,10 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
161
161
|
|
|
162
162
|
|
|
163
163
|
var squares = [];
|
|
164
|
-
|
|
165
|
-
_kokopu["default"].forEachSquare(function (sq) {
|
|
164
|
+
(0, _kokopu.forEachSquare)(function (sq) {
|
|
166
165
|
return squares.push(_this2.renderSquare(squareSize, colorset, sq));
|
|
167
166
|
}); // Render coordinates.
|
|
168
167
|
|
|
169
|
-
|
|
170
168
|
var rankCoordinates = [];
|
|
171
169
|
var fileCoordinates = [];
|
|
172
170
|
|
|
@@ -221,12 +219,10 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
221
219
|
var _this4 = this;
|
|
222
220
|
|
|
223
221
|
var pieces = [];
|
|
224
|
-
|
|
225
|
-
_kokopu["default"].forEachSquare(function (sq) {
|
|
222
|
+
(0, _kokopu.forEachSquare)(function (sq) {
|
|
226
223
|
return pieces.push(_this4.renderPieceAnimated(positionBefore, move, alpha, squareSize, pieceset, sq));
|
|
227
224
|
});
|
|
228
|
-
|
|
229
|
-
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, pieces, this.renderMoveArrow(move, alpha, squareSize, colorset), this.renderTurnFlag(_kokopu["default"].oppositeColor(positionBefore.turn()), squareSize, pieceset));
|
|
225
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, pieces, this.renderMoveArrow(move, alpha, squareSize, colorset), this.renderTurnFlag((0, _kokopu.oppositeColor)(positionBefore.turn()), squareSize, pieceset));
|
|
230
226
|
}
|
|
231
227
|
/**
|
|
232
228
|
* Render the board content when the animation has been completed (or if there is no animation).
|
|
@@ -246,15 +242,13 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
246
242
|
|
|
247
243
|
var pieces = [];
|
|
248
244
|
var handles = [];
|
|
249
|
-
|
|
250
|
-
_kokopu["default"].forEachSquare(function (sq) {
|
|
245
|
+
(0, _kokopu.forEachSquare)(function (sq) {
|
|
251
246
|
pieces.push(_this5.renderPiece(position, squareSize, pieceset, sq));
|
|
252
247
|
|
|
253
248
|
if (_this5.props.interactionMode) {
|
|
254
249
|
handles.push(_this5.renderSquareHandle(position, squareSize, sq));
|
|
255
250
|
}
|
|
256
251
|
});
|
|
257
|
-
|
|
258
252
|
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, this.renderSquareMarkers(sqm, squareSize, colorset), this.renderHoveredSquare(squareSize, colorset), pieces, this.renderTextMarkers(txtm, squareSize, colorset), this.renderArrowMarkers(arm, squareSize, colorset), this.renderMoveArrow(move, 1, squareSize, colorset), handles, this.renderPromotionDrawer(position, squareSize, colorset, pieceset), this.renderDraggedPiece(position, squareSize, pieceset), this.renderDraggedArrow(squareSize, colorset), this.renderTurnFlag(position.turn(), squareSize, pieceset));
|
|
259
253
|
}
|
|
260
254
|
}, {
|
|
@@ -270,7 +264,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
270
264
|
y: y,
|
|
271
265
|
width: squareSize,
|
|
272
266
|
height: squareSize,
|
|
273
|
-
fill: colorset[_kokopu
|
|
267
|
+
fill: colorset[(0, _kokopu.squareColor)(sq)]
|
|
274
268
|
});
|
|
275
269
|
}
|
|
276
270
|
}, {
|
|
@@ -905,9 +899,9 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
905
899
|
}, {
|
|
906
900
|
key: "getSquareCoordinates",
|
|
907
901
|
value: function getSquareCoordinates(squareSize, sq) {
|
|
908
|
-
var
|
|
909
|
-
file =
|
|
910
|
-
rank =
|
|
902
|
+
var _squareToCoordinates = (0, _kokopu.squareToCoordinates)(sq),
|
|
903
|
+
file = _squareToCoordinates.file,
|
|
904
|
+
rank = _squareToCoordinates.rank;
|
|
911
905
|
|
|
912
906
|
var x = this.props.flipped ? (7 - file) * squareSize : file * squareSize;
|
|
913
907
|
var y = this.props.flipped ? rank * squareSize : (7 - rank) * squareSize;
|
|
@@ -956,7 +950,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
956
950
|
} // Compute the position after the move and return the result.
|
|
957
951
|
|
|
958
952
|
|
|
959
|
-
var positionAfter = new _kokopu
|
|
953
|
+
var positionAfter = new _kokopu.Position(positionInfo.position);
|
|
960
954
|
positionAfter.play(moveInfo.move);
|
|
961
955
|
return {
|
|
962
956
|
positionError: false,
|
|
@@ -975,7 +969,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
975
969
|
value: function getSquareAt(squareSize, x, y) {
|
|
976
970
|
var file = this.props.flipped ? 7 - Math.floor(x / squareSize) : Math.floor(x / squareSize);
|
|
977
971
|
var rank = this.props.flipped ? Math.floor(y / squareSize) : 7 - Math.floor(y / squareSize);
|
|
978
|
-
return file >= 0 && file < 8 && rank >= 0 && rank < 8 ? _kokopu
|
|
972
|
+
return file >= 0 && file < 8 && rank >= 0 && rank < 8 ? (0, _kokopu.coordinatesToSquare)(file, rank) : '-';
|
|
979
973
|
}
|
|
980
974
|
/**
|
|
981
975
|
* Return the DOM ID of an arrow tip with the given color.
|
|
@@ -1146,26 +1140,22 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
1146
1140
|
exports["default"] = Chessboard;
|
|
1147
1141
|
Chessboard.propTypes = {
|
|
1148
1142
|
/**
|
|
1149
|
-
* Displayed position. Can be a [kokopu.Position](https://kokopu.yo35.org/docs/current/Position.html) object,
|
|
1143
|
+
* Displayed position. Can be a [kokopu.Position](https://kokopu.yo35.org/docs/current/classes/Position.html) object,
|
|
1150
1144
|
* a [FEN string](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation),
|
|
1151
1145
|
* `'start'` (usual starting position), or `'empty'` (empty board).
|
|
1152
1146
|
*
|
|
1153
1147
|
* Optionally, the FEN string can be prefixed with `'variant:'`, `variant` corresponding to one of the
|
|
1154
|
-
* [game variant](https://kokopu.yo35.org/docs/current/
|
|
1148
|
+
* [game variant](https://kokopu.yo35.org/docs/current/types/GameVariant.html) supported by Kokopu. For instance:
|
|
1155
1149
|
* `'chess960:nrkbqrbn/pppppppp/8/8/8/8/PPPPPPPP/NRKBQRBN w KQkq - 0 1'`.
|
|
1156
1150
|
*/
|
|
1157
|
-
position: _propTypes["default"].oneOfType([_propTypes["default"].instanceOf(_kokopu
|
|
1151
|
+
position: _propTypes["default"].oneOfType([_propTypes["default"].instanceOf(_kokopu.Position), _propTypes["default"].string]),
|
|
1158
1152
|
|
|
1159
1153
|
/**
|
|
1160
|
-
* Displayed move (optional), defined either as a [kokopu.MoveDescriptor](https://kokopu.yo35.org/docs/current/MoveDescriptor.html) object
|
|
1154
|
+
* Displayed move (optional), defined either as a [kokopu.MoveDescriptor](https://kokopu.yo35.org/docs/current/classes/MoveDescriptor.html) object
|
|
1161
1155
|
* or as a [SAN string](https://en.wikipedia.org/wiki/Algebraic_notation_(chess)) (e.g. `'Nf3'`). In both cases, it must represent
|
|
1162
1156
|
* a legal move in position defined in attribute `position`.
|
|
1163
1157
|
*/
|
|
1164
|
-
move: _propTypes["default"].oneOfType([
|
|
1165
|
-
if (!_kokopu["default"].isMoveDescriptor(props[propName])) {
|
|
1166
|
-
return new Error("Invalid prop ".concat(propName, " supplied to ").concat(componentName, ". Validation failed."));
|
|
1167
|
-
}
|
|
1168
|
-
}, _propTypes["default"].string]),
|
|
1158
|
+
move: _propTypes["default"].oneOfType([_propTypes["default"].instanceOf(_kokopu.MoveDescriptor), _propTypes["default"].string]),
|
|
1169
1159
|
|
|
1170
1160
|
/**
|
|
1171
1161
|
* Square markers, defined as a "square -> color" struct (e.g. `{ e4: 'g', d5: 'r' }`) or as a comma-separated CSL string (e.g. `'Rd5,Ge4'`).
|
|
@@ -1332,7 +1322,7 @@ function computeCoordinateFontSize(squareSize) {
|
|
|
1332
1322
|
|
|
1333
1323
|
|
|
1334
1324
|
function parsePosition(position) {
|
|
1335
|
-
if (position instanceof _kokopu
|
|
1325
|
+
if (position instanceof _kokopu.Position) {
|
|
1336
1326
|
return {
|
|
1337
1327
|
error: false,
|
|
1338
1328
|
position: position
|
|
@@ -1341,11 +1331,11 @@ function parsePosition(position) {
|
|
|
1341
1331
|
try {
|
|
1342
1332
|
return {
|
|
1343
1333
|
error: false,
|
|
1344
|
-
position: new _kokopu
|
|
1334
|
+
position: new _kokopu.Position(position)
|
|
1345
1335
|
};
|
|
1346
1336
|
} catch (e) {
|
|
1347
1337
|
// istanbul ignore else
|
|
1348
|
-
if (e instanceof _kokopu
|
|
1338
|
+
if (e instanceof _kokopu.exception.InvalidFEN) {
|
|
1349
1339
|
return {
|
|
1350
1340
|
error: true,
|
|
1351
1341
|
message: e.message
|
|
@@ -1367,7 +1357,7 @@ function parsePosition(position) {
|
|
|
1367
1357
|
|
|
1368
1358
|
|
|
1369
1359
|
function parseMove(position, move) {
|
|
1370
|
-
if (_kokopu
|
|
1360
|
+
if (move instanceof _kokopu.MoveDescriptor) {
|
|
1371
1361
|
return {
|
|
1372
1362
|
error: false,
|
|
1373
1363
|
move: move
|
|
@@ -1380,7 +1370,7 @@ function parseMove(position, move) {
|
|
|
1380
1370
|
};
|
|
1381
1371
|
} catch (e) {
|
|
1382
1372
|
// istanbul ignore else
|
|
1383
|
-
if (e instanceof _kokopu
|
|
1373
|
+
if (e instanceof _kokopu.exception.InvalidNotation) {
|
|
1384
1374
|
return {
|
|
1385
1375
|
error: true,
|
|
1386
1376
|
message: e.message
|
package/dist/lib/ErrorBox.js
CHANGED
|
@@ -11,6 +11,8 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
11
11
|
|
|
12
12
|
var _i18n = _interopRequireDefault(require("./i18n"));
|
|
13
13
|
|
|
14
|
+
var _util = require("./impl/util");
|
|
15
|
+
|
|
14
16
|
require("./css/error_box.css");
|
|
15
17
|
|
|
16
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
@@ -133,7 +135,7 @@ function ellipsisAt(text, pos, backwardCharacters, forwardCharacters, lineNumber
|
|
|
133
135
|
var secondLine = Array(1 + e1.length + pos - p1).join(' ') + '^';
|
|
134
136
|
|
|
135
137
|
if (lineNumber) {
|
|
136
|
-
secondLine +=
|
|
138
|
+
secondLine += " (".concat((0, _util.fillPlaceholder)(_i18n["default"].LINE, lineNumber), ")");
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
return excerpt + '\n' + secondLine;
|
package/dist/lib/Movetext.js
CHANGED
|
@@ -11,10 +11,12 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
11
11
|
|
|
12
12
|
var _react = _interopRequireDefault(require("react"));
|
|
13
13
|
|
|
14
|
-
var _kokopu =
|
|
14
|
+
var _kokopu = require("kokopu");
|
|
15
15
|
|
|
16
16
|
var _HtmlSanitizer = _interopRequireDefault(require("./impl/HtmlSanitizer"));
|
|
17
17
|
|
|
18
|
+
var _util = require("./impl/util");
|
|
19
|
+
|
|
18
20
|
var _Chessboard = _interopRequireDefault(require("./Chessboard"));
|
|
19
21
|
|
|
20
22
|
var _ErrorBox = _interopRequireDefault(require("./ErrorBox"));
|
|
@@ -147,7 +149,7 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
147
149
|
}, sanitizeHtml(title));
|
|
148
150
|
var ratingElement = rating === undefined ? undefined : /*#__PURE__*/_react["default"].createElement("span", {
|
|
149
151
|
className: "kokopu-header-playerRating"
|
|
150
|
-
},
|
|
152
|
+
}, rating);
|
|
151
153
|
var separator = title === undefined || rating === undefined ? undefined : "\xA0"; // \u00a0 ==
|
|
152
154
|
|
|
153
155
|
var titleRatingGroup = title === undefined && rating === undefined ? undefined : /*#__PURE__*/_react["default"].createElement("span", {
|
|
@@ -225,7 +227,7 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
225
227
|
return undefined;
|
|
226
228
|
}
|
|
227
229
|
|
|
228
|
-
annotator = _i18n["default"].ANNOTATED_BY
|
|
230
|
+
annotator = (0, _util.fillPlaceholder)(_i18n["default"].ANNOTATED_BY, annotator);
|
|
229
231
|
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
230
232
|
className: "kokopu-header-annotator",
|
|
231
233
|
key: "annotator"
|
|
@@ -405,7 +407,7 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
405
407
|
return /*#__PURE__*/_react["default"].createElement("span", {
|
|
406
408
|
className: "kokopu-nag",
|
|
407
409
|
key: nag
|
|
408
|
-
}, _kokopu
|
|
410
|
+
}, (0, _kokopu.nagSymbol)(nag));
|
|
409
411
|
}); // Class
|
|
410
412
|
|
|
411
413
|
var nodeId = node.id();
|
|
@@ -706,14 +708,14 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
706
708
|
exports["default"] = Movetext;
|
|
707
709
|
Movetext.propTypes = {
|
|
708
710
|
/**
|
|
709
|
-
* Displayed position. Can be a [kokopu.Game](https://kokopu.yo35.org/docs/current/Game.html) object,
|
|
710
|
-
* a [kokopu.Database](https://kokopu.yo35.org/docs/current/Database.html) object,
|
|
711
|
+
* Displayed position. Can be a [kokopu.Game](https://kokopu.yo35.org/docs/current/classes/Game.html) object,
|
|
712
|
+
* a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html) object,
|
|
711
713
|
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation).
|
|
712
714
|
*/
|
|
713
|
-
game: _propTypes["default"].oneOfType([_propTypes["default"].instanceOf(_kokopu
|
|
715
|
+
game: _propTypes["default"].oneOfType([_propTypes["default"].instanceOf(_kokopu.Game), _propTypes["default"].instanceOf(_kokopu.Database), _propTypes["default"].string]),
|
|
714
716
|
|
|
715
717
|
/**
|
|
716
|
-
* Index of the game to display (only if attribute `game` is a [kokopu.Database](https://kokopu.yo35.org/docs/current/Database.html)
|
|
718
|
+
* Index of the game to display (only if attribute `game` is a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html)
|
|
717
719
|
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation)): `0` for the first game of the database/PGN, `1` for the second one, etc.
|
|
718
720
|
* If omitted, the first game of the database/PGN is displayed.
|
|
719
721
|
*/
|
|
@@ -759,7 +761,7 @@ Movetext.propTypes = {
|
|
|
759
761
|
|
|
760
762
|
/**
|
|
761
763
|
* ID of the selected move (or `'start'` for the beginning of the main variation).
|
|
762
|
-
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/Node.html#id) to get the ID of a game move.
|
|
764
|
+
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id) to get the ID of a game move.
|
|
763
765
|
*/
|
|
764
766
|
selection: _propTypes["default"].string,
|
|
765
767
|
|
|
@@ -773,7 +775,7 @@ Movetext.propTypes = {
|
|
|
773
775
|
/**
|
|
774
776
|
* Callback invoked when the user selects a move (only if `interactionMode` is set to `'selectMove'`).
|
|
775
777
|
*
|
|
776
|
-
* @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/current/Node.html#id)),
|
|
778
|
+
* @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id)),
|
|
777
779
|
* `'start'` for the beginning of the main variation, or `undefined` if the user unselects the previously selected move.
|
|
778
780
|
* @param {string} evtOrigin Origin of the event. Can be:
|
|
779
781
|
* - `'key-first'`: the event has been triggered by the "go-to-first-move" key (aka. the home key),
|
|
@@ -785,7 +787,7 @@ Movetext.propTypes = {
|
|
|
785
787
|
onMoveSelected: _propTypes["default"].func
|
|
786
788
|
};
|
|
787
789
|
Movetext.defaultProps = {
|
|
788
|
-
game: new _kokopu
|
|
790
|
+
game: new _kokopu.Game(),
|
|
789
791
|
gameIndex: 0,
|
|
790
792
|
diagramOptions: {},
|
|
791
793
|
pieceSymbols: 'native',
|
|
@@ -863,21 +865,28 @@ function sanitizeHtml(text, sanitizer) {
|
|
|
863
865
|
|
|
864
866
|
|
|
865
867
|
function parseGame(game, gameIndex) {
|
|
866
|
-
if (game instanceof _kokopu
|
|
868
|
+
if (game instanceof _kokopu.Game) {
|
|
867
869
|
return {
|
|
868
870
|
error: false,
|
|
869
871
|
game: game
|
|
870
872
|
};
|
|
871
|
-
} else if (game instanceof _kokopu
|
|
873
|
+
} else if (game instanceof _kokopu.Database || typeof game === 'string') {
|
|
874
|
+
if (!Number.isInteger(gameIndex) || gameIndex < 0) {
|
|
875
|
+
return {
|
|
876
|
+
error: true,
|
|
877
|
+
message: _i18n["default"].INVALID_GAME_INDEX_ATTRIBUTE_ERROR_MESSAGE
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
|
|
872
881
|
try {
|
|
873
|
-
var result = game instanceof _kokopu
|
|
882
|
+
var result = game instanceof _kokopu.Database ? game.game(gameIndex) : (0, _kokopu.pgnRead)(game, gameIndex);
|
|
874
883
|
return {
|
|
875
884
|
error: false,
|
|
876
885
|
game: result
|
|
877
886
|
};
|
|
878
887
|
} catch (e) {
|
|
879
888
|
// istanbul ignore else
|
|
880
|
-
if (e instanceof _kokopu
|
|
889
|
+
if (e instanceof _kokopu.exception.InvalidPGN) {
|
|
881
890
|
return {
|
|
882
891
|
error: true,
|
|
883
892
|
message: e.message,
|
package/dist/lib/i18n.js
CHANGED
|
@@ -44,7 +44,8 @@ var i18n = {
|
|
|
44
44
|
},
|
|
45
45
|
ANNOTATED_BY: 'Annotated by {0}',
|
|
46
46
|
INVALID_PGN_ERROR_TITLE: 'Invalid PGN string.',
|
|
47
|
-
INVALID_GAME_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game" attribute.'
|
|
47
|
+
INVALID_GAME_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game" attribute.',
|
|
48
|
+
INVALID_GAME_INDEX_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game index" attribute.'
|
|
48
49
|
};
|
|
49
50
|
var _default = i18n;
|
|
50
51
|
exports["default"] = _default;
|
package/dist/lib/impl/util.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.MIN_SQUARE_SIZE = exports.MAX_SQUARE_SIZE = void 0;
|
|
7
|
+
exports.fillPlaceholder = fillPlaceholder;
|
|
7
8
|
exports.generateRandomId = generateRandomId;
|
|
8
9
|
exports.isValidColor = isValidColor;
|
|
9
10
|
exports.isValidSquare = isValidSquare;
|
|
@@ -48,6 +49,17 @@ function generateRandomId() {
|
|
|
48
49
|
return result;
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
function fillPlaceholder(message) {
|
|
53
|
+
for (var _len = arguments.length, placeholderValues = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
54
|
+
placeholderValues[_key - 1] = arguments[_key];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return message.replace(/{(\d+)}/g, function (match, placeholder) {
|
|
58
|
+
var placeholderIndex = Number(placeholder);
|
|
59
|
+
return placeholderIndex < placeholderValues.length ? placeholderValues[placeholderIndex] : match;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
function sanitizeInteger(input, min, max) {
|
|
52
64
|
return Math.min(Math.max(Math.round(input), min), max);
|
|
53
65
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { Position, oppositeColor } from 'kokopu';
|
|
25
25
|
|
|
26
26
|
import { Chessboard, SquareMarkerIcon, TextMarkerIcon, ArrowMarkerIcon, flattenSquareMarkers, flattenTextMarkers, flattenArrowMarkers } from '../../src/index';
|
|
27
27
|
import { buildComponentDemoCode } from './util';
|
|
@@ -53,7 +53,7 @@ export default class Page extends React.Component {
|
|
|
53
53
|
constructor(props) {
|
|
54
54
|
super(props);
|
|
55
55
|
this.state = {
|
|
56
|
-
position: new
|
|
56
|
+
position: new Position(),
|
|
57
57
|
flipped: false,
|
|
58
58
|
interactionMode: 'movePieces',
|
|
59
59
|
pieceEditMode: 'wp',
|
|
@@ -83,12 +83,12 @@ export default class Page extends React.Component {
|
|
|
83
83
|
<FormControlLabel label="Flip"
|
|
84
84
|
control={<Switch checked={this.state.flipped} onChange={() => this.set('flipped', !this.state.flipped)} color="primary" />}
|
|
85
85
|
/>
|
|
86
|
-
<Button color="primary" size="small" variant="contained" onClick={() => this.handleTurnClicked(
|
|
86
|
+
<Button color="primary" size="small" variant="contained" onClick={() => this.handleTurnClicked(oppositeColor(this.state.position.turn()))}>
|
|
87
87
|
Change turn
|
|
88
88
|
</Button>
|
|
89
89
|
<ButtonGroup color="primary" size="small">
|
|
90
|
-
<Button onClick={() => this.set('position', new
|
|
91
|
-
<Button onClick={() => this.set('position', new
|
|
90
|
+
<Button onClick={() => this.set('position', new Position('empty'))}>Clear</Button>
|
|
91
|
+
<Button onClick={() => this.set('position', new Position())}>Reset</Button>
|
|
92
92
|
</ButtonGroup>
|
|
93
93
|
</Stack>
|
|
94
94
|
<Box>
|
|
@@ -266,20 +266,20 @@ export default class Page extends React.Component {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
handleTurnClicked(newTurn) {
|
|
269
|
-
let newPosition = new
|
|
269
|
+
let newPosition = new Position(this.state.position);
|
|
270
270
|
newPosition.turn(newTurn);
|
|
271
271
|
this.set('position', newPosition);
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
handlePieceMoved(from, to) {
|
|
275
|
-
let newPosition = new
|
|
275
|
+
let newPosition = new Position(this.state.position);
|
|
276
276
|
newPosition.square(to, newPosition.square(from));
|
|
277
277
|
newPosition.square(from, '-');
|
|
278
278
|
this.set('position', newPosition);
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
handleMovePlayed(move) {
|
|
282
|
-
let newPosition = new
|
|
282
|
+
let newPosition = new Position(this.state.position);
|
|
283
283
|
newPosition.play(move);
|
|
284
284
|
this.set('position', newPosition);
|
|
285
285
|
}
|
|
@@ -318,7 +318,7 @@ export default class Page extends React.Component {
|
|
|
318
318
|
this.set('textMarkers', newTextMarkers);
|
|
319
319
|
}
|
|
320
320
|
else if (this.state.interactionMode === 'addRemovePieces') {
|
|
321
|
-
let newPosition = new
|
|
321
|
+
let newPosition = new Position(this.state.position);
|
|
322
322
|
newPosition.square(sq, newPosition.square(sq) === this.state.pieceEditMode ? '-' : this.state.pieceEditMode);
|
|
323
323
|
this.set('position', newPosition);
|
|
324
324
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { exception, Position } from 'kokopu';
|
|
25
25
|
|
|
26
26
|
import { Chessboard, ArrowMarkerIcon } from '../../src/index';
|
|
27
27
|
import { buildComponentDemoCode } from './util';
|
|
@@ -45,8 +45,8 @@ export default class Page extends React.Component {
|
|
|
45
45
|
|
|
46
46
|
constructor(props) {
|
|
47
47
|
super(props);
|
|
48
|
-
let position = new
|
|
49
|
-
let positionAfter = new
|
|
48
|
+
let position = new Position();
|
|
49
|
+
let positionAfter = new Position(position);
|
|
50
50
|
positionAfter.play('e4');
|
|
51
51
|
this.state = {
|
|
52
52
|
position: position,
|
|
@@ -88,8 +88,8 @@ export default class Page extends React.Component {
|
|
|
88
88
|
<TextField label="Move" variant="standard" value={this.state.editedMove} onChange={evt => this.set('editedMove', evt.target.value)} />
|
|
89
89
|
<Button color="primary" size="small" variant="contained" onClick={() => this.handlePlayClicked()}>Play</Button>
|
|
90
90
|
<ButtonGroup color="primary" size="small">
|
|
91
|
-
<Button onClick={() => this.setPosition(new
|
|
92
|
-
<Button onClick={() => this.setPosition(new
|
|
91
|
+
<Button onClick={() => this.setPosition(new Position('empty'))}>Clear</Button>
|
|
92
|
+
<Button onClick={() => this.setPosition(new Position())}>Reset</Button>
|
|
93
93
|
</ButtonGroup>
|
|
94
94
|
</Stack>
|
|
95
95
|
</>);
|
|
@@ -164,7 +164,7 @@ export default class Page extends React.Component {
|
|
|
164
164
|
|
|
165
165
|
handlePlayClicked() {
|
|
166
166
|
let newState = {};
|
|
167
|
-
let currentPosition = new
|
|
167
|
+
let currentPosition = new Position(this.state.positionAfter ? this.state.positionAfter : this.state.position);
|
|
168
168
|
let move = this.state.editedMove.trim();
|
|
169
169
|
if (move === '') {
|
|
170
170
|
newState.position = currentPosition;
|
|
@@ -176,11 +176,11 @@ export default class Page extends React.Component {
|
|
|
176
176
|
let moveDescriptor = currentPosition.notation(move);
|
|
177
177
|
newState.position = currentPosition;
|
|
178
178
|
newState.playedMove = currentPosition.notation(moveDescriptor);
|
|
179
|
-
newState.positionAfter = new
|
|
179
|
+
newState.positionAfter = new Position(currentPosition);
|
|
180
180
|
newState.positionAfter.play(moveDescriptor);
|
|
181
181
|
}
|
|
182
182
|
catch (e) {
|
|
183
|
-
if (e instanceof
|
|
183
|
+
if (e instanceof exception.InvalidNotation) {
|
|
184
184
|
newState.position = currentPosition;
|
|
185
185
|
newState.playedMove = move;
|
|
186
186
|
newState.positionAfter = null;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { pgnRead } from 'kokopu';
|
|
25
25
|
|
|
26
26
|
import { Chessboard, Movetext } from '../../src/index';
|
|
27
27
|
import { buildComponentDemoCode } from './util';
|
|
@@ -143,7 +143,7 @@ export default class Page extends React.Component {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
getCurrentPositionAndAnnotations() {
|
|
146
|
-
let game =
|
|
146
|
+
let game = pgnRead(this.state.pgn, 0);
|
|
147
147
|
if (this.state.selection === 'start') {
|
|
148
148
|
let mainVariation = game.mainVariation();
|
|
149
149
|
return { position: mainVariation.initialPosition(), csl: mainVariation.tag('csl'), cal: mainVariation.tag('cal') };
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { Position } from 'kokopu';
|
|
25
25
|
import testApp from './common/test_app';
|
|
26
26
|
import { Chessboard } from '../src/index';
|
|
27
27
|
|
|
@@ -30,6 +30,6 @@ testApp([ /* eslint-disable react/jsx-key */
|
|
|
30
30
|
<Chessboard position="empty" />,
|
|
31
31
|
<Chessboard position="something invalid" />,
|
|
32
32
|
<Chessboard position="r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3" />,
|
|
33
|
-
<Chessboard position={new
|
|
33
|
+
<Chessboard position={new Position('8/8/1r6/8/5k1K/8/8/8 b - - 0 1')} />,
|
|
34
34
|
<Chessboard position={42} />,
|
|
35
35
|
]); /* eslint-enable react/jsx-key */
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { Position } from 'kokopu';
|
|
25
25
|
import testApp from './common/test_app';
|
|
26
26
|
import { Chessboard } from '../src/index';
|
|
27
27
|
|
|
@@ -30,5 +30,5 @@ testApp([ /* eslint-disable react/jsx-key */
|
|
|
30
30
|
<Chessboard flipped={true} position="empty" />,
|
|
31
31
|
<Chessboard flipped={true} position="something invalid" />,
|
|
32
32
|
<Chessboard flipped={true} position="r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3" />,
|
|
33
|
-
<Chessboard flipped={true} position={new
|
|
33
|
+
<Chessboard flipped={true} position={new Position('8/8/1r6/8/5k1K/8/8/8 b - - 0 1')} />,
|
|
34
34
|
]); /* eslint-enable react/jsx-key */
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { Position } from 'kokopu';
|
|
25
25
|
import testApp from './common/test_app';
|
|
26
26
|
import { Chessboard } from '../src/index';
|
|
27
27
|
|
|
28
|
-
let pos = new
|
|
28
|
+
let pos = new Position('r1bqkbnr/1ppp1ppp/p1n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 4');
|
|
29
29
|
let move = pos.notation('Bxc6');
|
|
30
30
|
|
|
31
31
|
testApp([ /* eslint-disable react/jsx-key */
|
|
@@ -21,17 +21,17 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { Game, pgnRead } from 'kokopu';
|
|
25
25
|
import testApp from './common/test_app';
|
|
26
26
|
import { Movetext } from '../src/index';
|
|
27
27
|
|
|
28
28
|
import pgn from './common/games.pgn';
|
|
29
29
|
|
|
30
|
-
let game = new
|
|
30
|
+
let game = new Game();
|
|
31
31
|
game.mainVariation().play('e4').play('e5').play('Bc4').play('Nc6').play('Qh5').play('Nf6').play('Qxf7#');
|
|
32
32
|
game.result('1-0');
|
|
33
33
|
|
|
34
|
-
let database =
|
|
34
|
+
let database = pgnRead(pgn);
|
|
35
35
|
|
|
36
36
|
testApp([ /* eslint-disable react/jsx-key */
|
|
37
37
|
<Movetext game={game} />,
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
import React from 'react';
|
|
24
|
-
import
|
|
24
|
+
import { pgnRead } from 'kokopu';
|
|
25
25
|
import testApp from './common/test_app';
|
|
26
26
|
import { Movetext } from '../src/index';
|
|
27
27
|
|
|
28
28
|
import pgn from './common/games.pgn';
|
|
29
29
|
import dummyPgn from './common/dummy.pgn';
|
|
30
30
|
|
|
31
|
-
let database =
|
|
31
|
+
let database = pgnRead(pgn);
|
|
32
32
|
|
|
33
33
|
testApp([ /* eslint-disable react/jsx-key */
|
|
34
|
+
<Movetext game={pgn} gameIndex={99} />,
|
|
34
35
|
<Movetext game={database} gameIndex={99} />,
|
|
35
36
|
<Movetext game={dummyPgn} />,
|
|
36
|
-
<Movetext game={
|
|
37
|
+
<Movetext game={pgnRead(dummyPgn)} gameIndex={1} />,
|
|
37
38
|
<Movetext game={42} />,
|
|
38
39
|
], 'width-600'); /* eslint-enable react/jsx-key */
|
|
@@ -87,8 +87,8 @@ probably to assure himself that the combination was sound and that he had a forc
|
|
|
87
87
|
[White "1<sup>st</sup> <em>player</em>"]
|
|
88
88
|
[Black "2<sub>nd</sub> <i>player</i>"]
|
|
89
89
|
[Result "*"]
|
|
90
|
-
[WhiteElo "
|
|
91
|
-
[BlackElo "
|
|
90
|
+
[WhiteElo "2800"]
|
|
91
|
+
[BlackElo "1010"]
|
|
92
92
|
[WhiteTitle "<span class=\"myClass\">GM</span>"]
|
|
93
93
|
[BlackTitle "<span id=\"myId\">no-GM</span>"]
|
|
94
94
|
|
|
@@ -104,7 +104,7 @@ probably to assure himself that the combination was sound and that he had a forc
|
|
|
104
104
|
[Black "?"]
|
|
105
105
|
[Result "*"]
|
|
106
106
|
|
|
107
|
-
{I'm a <strong><ins>comment</ins></strong> with some <em class="myClass">HTML content</em> in it.<br/>
|
|
107
|
+
{I'm a <strong><ins>comment</ins></strong> with <del>some</del> <em class="myClass">HTML content</em> in it.<br/>
|
|
108
108
|
Lists are supported:
|
|
109
109
|
<ul>
|
|
110
110
|
<li>1<sup>st</sup> point</li>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kokopu-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "A React-based library to create and display chessboard and chess-related components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chess",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
".nycrc.yml"
|
|
32
32
|
],
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"kokopu": "^
|
|
34
|
+
"kokopu": "^3.0.0",
|
|
35
35
|
"react": "17.x.x || 18.x.x"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
@@ -42,22 +42,22 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@babel/cli": "^7.18.10",
|
|
45
|
-
"@babel/core": "^7.18.
|
|
45
|
+
"@babel/core": "^7.18.13",
|
|
46
46
|
"@babel/preset-env": "^7.18.10",
|
|
47
47
|
"@babel/preset-react": "^7.18.6",
|
|
48
48
|
"@emotion/react": "^11.10.0",
|
|
49
49
|
"@emotion/styled": "^11.10.0",
|
|
50
|
-
"@mui/material": "^5.
|
|
50
|
+
"@mui/material": "^5.10.2",
|
|
51
51
|
"babel-loader": "^8.2.5",
|
|
52
52
|
"babel-plugin-istanbul": "^6.1.1",
|
|
53
53
|
"copy-webpack-plugin": "^11.0.0",
|
|
54
54
|
"coveralls": "^3.1.1",
|
|
55
55
|
"css-loader": "^6.7.1",
|
|
56
|
-
"eslint": "^8.
|
|
57
|
-
"eslint-plugin-react": "^7.
|
|
56
|
+
"eslint": "^8.22.0",
|
|
57
|
+
"eslint-plugin-react": "^7.31.0",
|
|
58
58
|
"html-webpack-plugin": "^5.5.0",
|
|
59
59
|
"img-diff-js": "^0.5.2",
|
|
60
|
-
"kokopu": "^
|
|
60
|
+
"kokopu": "^3.0.0",
|
|
61
61
|
"mocha": "^10.0.0",
|
|
62
62
|
"null-loader": "^4.0.1",
|
|
63
63
|
"nyc": "^15.1.0",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"react-dom": "^18.2.0",
|
|
66
66
|
"react-styleguidist": "^11.2.0",
|
|
67
67
|
"selenium-webdriver": "^4.3.1",
|
|
68
|
-
"ssh2-sftp-client": "^9.0.
|
|
68
|
+
"ssh2-sftp-client": "^9.0.3",
|
|
69
69
|
"style-loader": "^3.3.1",
|
|
70
70
|
"unit.js": "^2.1.1",
|
|
71
71
|
"webpack": "^5.74.0",
|
package/src/Chessboard.js
CHANGED
|
@@ -24,7 +24,7 @@ import PropTypes from 'prop-types';
|
|
|
24
24
|
import React from 'react';
|
|
25
25
|
import Draggable from 'react-draggable';
|
|
26
26
|
import { Motion, spring } from 'react-motion';
|
|
27
|
-
import
|
|
27
|
+
import { exception, MoveDescriptor, Position, coordinatesToSquare, forEachSquare, oppositeColor, squareColor, squareToCoordinates } from 'kokopu';
|
|
28
28
|
|
|
29
29
|
import colorsets from './impl/colorsets';
|
|
30
30
|
import piecesets from './impl/piecesets';
|
|
@@ -102,7 +102,7 @@ export default class Chessboard extends React.Component {
|
|
|
102
102
|
|
|
103
103
|
// Render the squares.
|
|
104
104
|
let squares = [];
|
|
105
|
-
|
|
105
|
+
forEachSquare(sq => squares.push(this.renderSquare(squareSize, colorset, sq)));
|
|
106
106
|
|
|
107
107
|
// Render coordinates.
|
|
108
108
|
let rankCoordinates = [];
|
|
@@ -155,12 +155,12 @@ export default class Chessboard extends React.Component {
|
|
|
155
155
|
*/
|
|
156
156
|
renderBoardContentAnimated(positionBefore, move, alpha, squareSize, colorset, pieceset) {
|
|
157
157
|
let pieces = [];
|
|
158
|
-
|
|
158
|
+
forEachSquare(sq => pieces.push(this.renderPieceAnimated(positionBefore, move, alpha, squareSize, pieceset, sq)));
|
|
159
159
|
return (
|
|
160
160
|
<>
|
|
161
161
|
{pieces}
|
|
162
162
|
{this.renderMoveArrow(move, alpha, squareSize, colorset)}
|
|
163
|
-
{this.renderTurnFlag(
|
|
163
|
+
{this.renderTurnFlag(oppositeColor(positionBefore.turn()), squareSize, pieceset)}
|
|
164
164
|
</>
|
|
165
165
|
);
|
|
166
166
|
}
|
|
@@ -178,7 +178,7 @@ export default class Chessboard extends React.Component {
|
|
|
178
178
|
// Render the square-related objects.
|
|
179
179
|
let pieces = [];
|
|
180
180
|
let handles = [];
|
|
181
|
-
|
|
181
|
+
forEachSquare(sq => {
|
|
182
182
|
pieces.push(this.renderPiece(position, squareSize, pieceset, sq));
|
|
183
183
|
if (this.props.interactionMode) {
|
|
184
184
|
handles.push(this.renderSquareHandle(position, squareSize, sq));
|
|
@@ -203,7 +203,7 @@ export default class Chessboard extends React.Component {
|
|
|
203
203
|
|
|
204
204
|
renderSquare(squareSize, colorset, sq) {
|
|
205
205
|
let { x, y } = this.getSquareCoordinates(squareSize, sq);
|
|
206
|
-
return <rect key={sq} x={x} y={y} width={squareSize} height={squareSize} fill={colorset[
|
|
206
|
+
return <rect key={sq} x={x} y={y} width={squareSize} height={squareSize} fill={colorset[squareColor(sq)]} />;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
renderHoveredSquare(squareSize, colorset) {
|
|
@@ -575,7 +575,7 @@ export default class Chessboard extends React.Component {
|
|
|
575
575
|
* Return the (x,y) coordinates of the given square in the SVG canvas.
|
|
576
576
|
*/
|
|
577
577
|
getSquareCoordinates(squareSize, sq) {
|
|
578
|
-
let { file, rank } =
|
|
578
|
+
let { file, rank } = squareToCoordinates(sq);
|
|
579
579
|
let x = this.props.flipped ? (7 - file) * squareSize : file * squareSize;
|
|
580
580
|
let y = this.props.flipped ? rank * squareSize : (7 - rank) * squareSize;
|
|
581
581
|
return { x: x, y: y };
|
|
@@ -604,7 +604,7 @@ export default class Chessboard extends React.Component {
|
|
|
604
604
|
}
|
|
605
605
|
|
|
606
606
|
// Compute the position after the move and return the result.
|
|
607
|
-
let positionAfter = new
|
|
607
|
+
let positionAfter = new Position(positionInfo.position);
|
|
608
608
|
positionAfter.play(moveInfo.move);
|
|
609
609
|
return { positionError: false, moveError: false, positionBefore: positionInfo.position, move: moveInfo.move, position: positionAfter };
|
|
610
610
|
}
|
|
@@ -615,7 +615,7 @@ export default class Chessboard extends React.Component {
|
|
|
615
615
|
getSquareAt(squareSize, x, y) {
|
|
616
616
|
let file = this.props.flipped ? 7 - Math.floor(x / squareSize) : Math.floor(x / squareSize);
|
|
617
617
|
let rank = this.props.flipped ? Math.floor(y / squareSize) : 7 - Math.floor(y / squareSize);
|
|
618
|
-
return file >= 0 && file < 8 && rank >= 0 && rank < 8 ?
|
|
618
|
+
return file >= 0 && file < 8 && rank >= 0 && rank < 8 ? coordinatesToSquare(file, rank) : '-';
|
|
619
619
|
}
|
|
620
620
|
|
|
621
621
|
/**
|
|
@@ -760,30 +760,26 @@ export default class Chessboard extends React.Component {
|
|
|
760
760
|
Chessboard.propTypes = {
|
|
761
761
|
|
|
762
762
|
/**
|
|
763
|
-
* Displayed position. Can be a [kokopu.Position](https://kokopu.yo35.org/docs/current/Position.html) object,
|
|
763
|
+
* Displayed position. Can be a [kokopu.Position](https://kokopu.yo35.org/docs/current/classes/Position.html) object,
|
|
764
764
|
* a [FEN string](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation),
|
|
765
765
|
* `'start'` (usual starting position), or `'empty'` (empty board).
|
|
766
766
|
*
|
|
767
767
|
* Optionally, the FEN string can be prefixed with `'variant:'`, `variant` corresponding to one of the
|
|
768
|
-
* [game variant](https://kokopu.yo35.org/docs/current/
|
|
768
|
+
* [game variant](https://kokopu.yo35.org/docs/current/types/GameVariant.html) supported by Kokopu. For instance:
|
|
769
769
|
* `'chess960:nrkbqrbn/pppppppp/8/8/8/8/PPPPPPPP/NRKBQRBN w KQkq - 0 1'`.
|
|
770
770
|
*/
|
|
771
771
|
position: PropTypes.oneOfType([
|
|
772
|
-
PropTypes.instanceOf(
|
|
772
|
+
PropTypes.instanceOf(Position),
|
|
773
773
|
PropTypes.string
|
|
774
774
|
]),
|
|
775
775
|
|
|
776
776
|
/**
|
|
777
|
-
* Displayed move (optional), defined either as a [kokopu.MoveDescriptor](https://kokopu.yo35.org/docs/current/MoveDescriptor.html) object
|
|
777
|
+
* Displayed move (optional), defined either as a [kokopu.MoveDescriptor](https://kokopu.yo35.org/docs/current/classes/MoveDescriptor.html) object
|
|
778
778
|
* or as a [SAN string](https://en.wikipedia.org/wiki/Algebraic_notation_(chess)) (e.g. `'Nf3'`). In both cases, it must represent
|
|
779
779
|
* a legal move in position defined in attribute `position`.
|
|
780
780
|
*/
|
|
781
781
|
move: PropTypes.oneOfType([
|
|
782
|
-
|
|
783
|
-
if (!kokopu.isMoveDescriptor(props[propName])) {
|
|
784
|
-
return new Error(`Invalid prop ${propName} supplied to ${componentName}. Validation failed.`);
|
|
785
|
-
}
|
|
786
|
-
},
|
|
782
|
+
PropTypes.instanceOf(MoveDescriptor),
|
|
787
783
|
PropTypes.string
|
|
788
784
|
]),
|
|
789
785
|
|
|
@@ -961,16 +957,16 @@ function computeCoordinateFontSize(squareSize) {
|
|
|
961
957
|
* Try to interpret the given object as a chess position.
|
|
962
958
|
*/
|
|
963
959
|
function parsePosition(position) {
|
|
964
|
-
if (position instanceof
|
|
960
|
+
if (position instanceof Position) {
|
|
965
961
|
return { error: false, position: position };
|
|
966
962
|
}
|
|
967
963
|
else if (typeof position === 'string') {
|
|
968
964
|
try {
|
|
969
|
-
return { error: false, position: new
|
|
965
|
+
return { error: false, position: new Position(position) };
|
|
970
966
|
}
|
|
971
967
|
catch (e) {
|
|
972
968
|
// istanbul ignore else
|
|
973
|
-
if (e instanceof
|
|
969
|
+
if (e instanceof exception.InvalidFEN) {
|
|
974
970
|
return { error: true, message: e.message };
|
|
975
971
|
}
|
|
976
972
|
else {
|
|
@@ -988,7 +984,7 @@ function parsePosition(position) {
|
|
|
988
984
|
* Try to interpret the given object `move` as a move descriptor based on the given position.
|
|
989
985
|
*/
|
|
990
986
|
function parseMove(position, move) {
|
|
991
|
-
if (
|
|
987
|
+
if (move instanceof MoveDescriptor) {
|
|
992
988
|
return { error: false, move: move };
|
|
993
989
|
}
|
|
994
990
|
else if (typeof move === 'string') {
|
|
@@ -997,7 +993,7 @@ function parseMove(position, move) {
|
|
|
997
993
|
}
|
|
998
994
|
catch (e) {
|
|
999
995
|
// istanbul ignore else
|
|
1000
|
-
if (e instanceof
|
|
996
|
+
if (e instanceof exception.InvalidNotation) {
|
|
1001
997
|
return { error: true, message: e.message };
|
|
1002
998
|
}
|
|
1003
999
|
else {
|
package/src/ErrorBox.js
CHANGED
|
@@ -24,6 +24,7 @@ import PropTypes from 'prop-types';
|
|
|
24
24
|
import React from 'react';
|
|
25
25
|
|
|
26
26
|
import i18n from './i18n';
|
|
27
|
+
import { fillPlaceholder } from './impl/util';
|
|
27
28
|
|
|
28
29
|
import './css/error_box.css';
|
|
29
30
|
|
|
@@ -125,7 +126,7 @@ function ellipsisAt(text, pos, backwardCharacters, forwardCharacters, lineNumber
|
|
|
125
126
|
excerpt = excerpt.replace(/\n|\r|\t/g, ' ');
|
|
126
127
|
let secondLine = Array(1 + e1.length + pos - p1).join(' ') + '^';
|
|
127
128
|
if (lineNumber) {
|
|
128
|
-
secondLine +=
|
|
129
|
+
secondLine += ` (${fillPlaceholder(i18n.LINE, lineNumber)})`;
|
|
129
130
|
}
|
|
130
131
|
return excerpt + '\n' + secondLine;
|
|
131
132
|
}
|
package/src/Movetext.js
CHANGED
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
|
|
23
23
|
import PropTypes from 'prop-types';
|
|
24
24
|
import React from 'react';
|
|
25
|
-
import
|
|
25
|
+
import { exception, Database, Game, nagSymbol, pgnRead } from 'kokopu';
|
|
26
26
|
|
|
27
27
|
import HtmlSanitizer from './impl/HtmlSanitizer';
|
|
28
|
+
import { fillPlaceholder } from './impl/util';
|
|
28
29
|
import Chessboard from './Chessboard';
|
|
29
30
|
import ErrorBox from './ErrorBox';
|
|
30
31
|
import { moveFormatter } from './formatmove';
|
|
@@ -85,7 +86,7 @@ export default class Movetext extends React.Component {
|
|
|
85
86
|
let colorTag = <span className="kokopu-colorTag"></span>;
|
|
86
87
|
let playerNameElement = <span className="kokopu-header-playerName">{sanitizeHtml(playerName)}</span>;
|
|
87
88
|
let titleElement = title === undefined ? undefined : <span className="kokopu-header-playerTitle">{sanitizeHtml(title)}</span>;
|
|
88
|
-
let ratingElement = rating === undefined ? undefined : <span className="kokopu-header-playerRating">{
|
|
89
|
+
let ratingElement = rating === undefined ? undefined : <span className="kokopu-header-playerRating">{rating}</span>;
|
|
89
90
|
let separator = title === undefined || rating === undefined ? undefined : '\u00a0'; // \u00a0 ==
|
|
90
91
|
let titleRatingGroup = title === undefined && rating === undefined ? undefined : <span className="kokopu-headerGroup-titleRating">{titleElement}{separator}{ratingElement}</span>;
|
|
91
92
|
return <div className={classNames.join(' ')} key={'player-' + color}>{colorTag}{playerNameElement}{titleRatingGroup}</div>;
|
|
@@ -128,7 +129,7 @@ export default class Movetext extends React.Component {
|
|
|
128
129
|
if (annotator === undefined) {
|
|
129
130
|
return undefined;
|
|
130
131
|
}
|
|
131
|
-
annotator = i18n.ANNOTATED_BY
|
|
132
|
+
annotator = fillPlaceholder(i18n.ANNOTATED_BY, annotator);
|
|
132
133
|
return <div className="kokopu-header-annotator" key="annotator">{sanitizeHtml(annotator)}</div>;
|
|
133
134
|
}
|
|
134
135
|
|
|
@@ -255,7 +256,7 @@ export default class Movetext extends React.Component {
|
|
|
255
256
|
let notationText = notationTextBuilder(node.notation());
|
|
256
257
|
|
|
257
258
|
// NAGs
|
|
258
|
-
let nagElements = node.nags().map(nag => <span className="kokopu-nag" key={nag}>{
|
|
259
|
+
let nagElements = node.nags().map(nag => <span className="kokopu-nag" key={nag}>{nagSymbol(nag)}</span>);
|
|
259
260
|
|
|
260
261
|
// Class
|
|
261
262
|
let nodeId = node.id();
|
|
@@ -482,18 +483,18 @@ export default class Movetext extends React.Component {
|
|
|
482
483
|
Movetext.propTypes = {
|
|
483
484
|
|
|
484
485
|
/**
|
|
485
|
-
* Displayed position. Can be a [kokopu.Game](https://kokopu.yo35.org/docs/current/Game.html) object,
|
|
486
|
-
* a [kokopu.Database](https://kokopu.yo35.org/docs/current/Database.html) object,
|
|
486
|
+
* Displayed position. Can be a [kokopu.Game](https://kokopu.yo35.org/docs/current/classes/Game.html) object,
|
|
487
|
+
* a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html) object,
|
|
487
488
|
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation).
|
|
488
489
|
*/
|
|
489
490
|
game: PropTypes.oneOfType([
|
|
490
|
-
PropTypes.instanceOf(
|
|
491
|
-
PropTypes.instanceOf(
|
|
491
|
+
PropTypes.instanceOf(Game),
|
|
492
|
+
PropTypes.instanceOf(Database),
|
|
492
493
|
PropTypes.string
|
|
493
494
|
]),
|
|
494
495
|
|
|
495
496
|
/**
|
|
496
|
-
* Index of the game to display (only if attribute `game` is a [kokopu.Database](https://kokopu.yo35.org/docs/current/Database.html)
|
|
497
|
+
* Index of the game to display (only if attribute `game` is a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html)
|
|
497
498
|
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation)): `0` for the first game of the database/PGN, `1` for the second one, etc.
|
|
498
499
|
* If omitted, the first game of the database/PGN is displayed.
|
|
499
500
|
*/
|
|
@@ -542,7 +543,7 @@ Movetext.propTypes = {
|
|
|
542
543
|
|
|
543
544
|
/**
|
|
544
545
|
* ID of the selected move (or `'start'` for the beginning of the main variation).
|
|
545
|
-
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/Node.html#id) to get the ID of a game move.
|
|
546
|
+
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id) to get the ID of a game move.
|
|
546
547
|
*/
|
|
547
548
|
selection: PropTypes.string,
|
|
548
549
|
|
|
@@ -556,7 +557,7 @@ Movetext.propTypes = {
|
|
|
556
557
|
/**
|
|
557
558
|
* Callback invoked when the user selects a move (only if `interactionMode` is set to `'selectMove'`).
|
|
558
559
|
*
|
|
559
|
-
* @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/current/Node.html#id)),
|
|
560
|
+
* @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id)),
|
|
560
561
|
* `'start'` for the beginning of the main variation, or `undefined` if the user unselects the previously selected move.
|
|
561
562
|
* @param {string} evtOrigin Origin of the event. Can be:
|
|
562
563
|
* - `'key-first'`: the event has been triggered by the "go-to-first-move" key (aka. the home key),
|
|
@@ -570,7 +571,7 @@ Movetext.propTypes = {
|
|
|
570
571
|
|
|
571
572
|
|
|
572
573
|
Movetext.defaultProps = {
|
|
573
|
-
game: new
|
|
574
|
+
game: new Game(),
|
|
574
575
|
gameIndex: 0,
|
|
575
576
|
diagramOptions: {},
|
|
576
577
|
pieceSymbols: 'native',
|
|
@@ -643,17 +644,20 @@ function sanitizeHtml(text, sanitizer) {
|
|
|
643
644
|
* Try to interpret the given object as a chess game.
|
|
644
645
|
*/
|
|
645
646
|
function parseGame(game, gameIndex) {
|
|
646
|
-
if (game instanceof
|
|
647
|
+
if (game instanceof Game) {
|
|
647
648
|
return { error: false, game: game };
|
|
648
649
|
}
|
|
649
|
-
else if (game instanceof
|
|
650
|
+
else if (game instanceof Database || typeof game === 'string') {
|
|
651
|
+
if (!Number.isInteger(gameIndex) || gameIndex < 0) {
|
|
652
|
+
return { error: true, message: i18n.INVALID_GAME_INDEX_ATTRIBUTE_ERROR_MESSAGE };
|
|
653
|
+
}
|
|
650
654
|
try {
|
|
651
|
-
|
|
655
|
+
const result = game instanceof Database ? game.game(gameIndex) : pgnRead(game, gameIndex);
|
|
652
656
|
return { error: false, game: result };
|
|
653
657
|
}
|
|
654
658
|
catch (e) {
|
|
655
659
|
// istanbul ignore else
|
|
656
|
-
if (e instanceof
|
|
660
|
+
if (e instanceof exception.InvalidPGN) {
|
|
657
661
|
return { error: true, message: e.message, text: e.pgn, errorIndex: e.index, lineNumber: e.lineNumber };
|
|
658
662
|
}
|
|
659
663
|
else {
|
package/src/i18n.js
CHANGED
|
@@ -36,6 +36,7 @@ const i18n = {
|
|
|
36
36
|
ANNOTATED_BY: 'Annotated by {0}',
|
|
37
37
|
INVALID_PGN_ERROR_TITLE: 'Invalid PGN string.',
|
|
38
38
|
INVALID_GAME_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game" attribute.',
|
|
39
|
+
INVALID_GAME_INDEX_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game index" attribute.',
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
export default i18n;
|
package/src/impl/util.js
CHANGED
|
@@ -35,6 +35,14 @@ export function generateRandomId() {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
export function fillPlaceholder(message, ...placeholderValues) {
|
|
39
|
+
return message.replace(/{(\d+)}/g, (match, placeholder) => {
|
|
40
|
+
const placeholderIndex = Number(placeholder);
|
|
41
|
+
return placeholderIndex < placeholderValues.length ? placeholderValues[placeholderIndex] : match;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
38
46
|
export function sanitizeInteger(input, min, max) {
|
|
39
47
|
return Math.min(Math.max(Math.round(input), min), max);
|
|
40
48
|
}
|
|
@@ -36,7 +36,7 @@ describe('Movetext graphic', function() {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
itChecksScreenshots(browserContext, '12_movetext_simple', [ 'game-0', 'game-1', 'game-2', 'game-3' ]);
|
|
39
|
-
itChecksScreenshots(browserContext, '13_movetext_error', [ 'wrong-game-index', 'pgn-parsing-error-1', 'pgn-parsing-error-2', 'wrong type' ]);
|
|
39
|
+
itChecksScreenshots(browserContext, '13_movetext_error', [ 'wrong-game-index-1', 'wrong-game-index-2', 'pgn-parsing-error-1', 'pgn-parsing-error-2', 'wrong type' ]);
|
|
40
40
|
itChecksScreenshots(browserContext, '14_movetext_html', [ 'html-in-headers', 'html-in-comments', 'filtered-tags-and-attributes' ]);
|
|
41
41
|
itChecksScreenshots(browserContext, '15_movetext_options', [ 'localized-piece-symbols', 'custom-piece-symbols', 'figurine-piece-symbols-and-diagram-options',
|
|
42
42
|
'hidden-diagrams' ]);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|