kokopu-react 1.5.5 → 1.6.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 +5 -0
- package/dist/lib/ArrowMarkerIcon.js +2 -2
- package/dist/lib/Chessboard.js +2 -2
- package/dist/lib/Movetext.js +41 -82
- package/dist/lib/formatmove.js +119 -0
- package/dist/lib/impl/HtmlSanitizer.js +8 -3
- package/dist/lib/index.js +14 -0
- package/graphic_test_app/common/games.pgn +11 -5
- package/graphic_test_app/common/smiley.png +0 -0
- package/package.json +6 -6
- package/scripts/test_graphic/webpack-config.js +4 -1
- package/src/Movetext.js +37 -59
- package/src/formatmove.js +91 -0
- package/src/impl/HtmlSanitizer.js +8 -2
- package/src/index.js +1 -0
- package/test/references/14_movetext_html/0.png +0 -0
- package/test/references/14_movetext_html/1.png +0 -0
- package/test/references/14_movetext_html/2.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -27,7 +27,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
|
|
|
27
27
|
|
|
28
28
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
29
29
|
|
|
30
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf
|
|
30
|
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
31
31
|
|
|
32
32
|
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
33
33
|
|
|
@@ -37,7 +37,7 @@ function _assertThisInitialized(self) { if (self === void 0) { throw new Referen
|
|
|
37
37
|
|
|
38
38
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
39
39
|
|
|
40
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
40
|
+
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
41
41
|
|
|
42
42
|
var ARROW_THICKNESS_FACTOR = 0.2;
|
|
43
43
|
/**
|
package/dist/lib/Chessboard.js
CHANGED
|
@@ -59,7 +59,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
|
|
|
59
59
|
|
|
60
60
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
61
61
|
|
|
62
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf
|
|
62
|
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
63
63
|
|
|
64
64
|
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
65
65
|
|
|
@@ -69,7 +69,7 @@ function _assertThisInitialized(self) { if (self === void 0) { throw new Referen
|
|
|
69
69
|
|
|
70
70
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
71
71
|
|
|
72
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
72
|
+
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
73
73
|
|
|
74
74
|
var TURN_FLAG_SPACING_FACTOR = 0.1;
|
|
75
75
|
var RANK_COORDINATE_WIDTH_FACTOR = 1;
|
package/dist/lib/Movetext.js
CHANGED
|
@@ -19,9 +19,9 @@ var _Chessboard = _interopRequireDefault(require("./Chessboard"));
|
|
|
19
19
|
|
|
20
20
|
var _ErrorBox = _interopRequireDefault(require("./ErrorBox"));
|
|
21
21
|
|
|
22
|
-
var
|
|
22
|
+
var _formatmove = require("./formatmove");
|
|
23
23
|
|
|
24
|
-
require("./
|
|
24
|
+
var _i18n = _interopRequireDefault(require("./i18n"));
|
|
25
25
|
|
|
26
26
|
require("./css/movetext.css");
|
|
27
27
|
|
|
@@ -49,7 +49,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
|
|
|
49
49
|
|
|
50
50
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
51
51
|
|
|
52
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf
|
|
52
|
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
53
53
|
|
|
54
54
|
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
55
55
|
|
|
@@ -59,7 +59,7 @@ function _assertThisInitialized(self) { if (self === void 0) { throw new Referen
|
|
|
59
59
|
|
|
60
60
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
61
61
|
|
|
62
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
62
|
+
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Display a chess game, i.e. the headers (name of the players, event, etc.), the moves, and all the related annotations if any (comments, variations, NAGs...).
|
|
@@ -254,7 +254,8 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
254
254
|
}, {
|
|
255
255
|
key: "renderBody",
|
|
256
256
|
value: function renderBody(game) {
|
|
257
|
-
|
|
257
|
+
var notationTextBuilder = (0, _formatmove.moveFormatter)(this.props.pieceSymbols);
|
|
258
|
+
return this.renderVariation(notationTextBuilder, game.mainVariation(), 'main-variation', true, game.result());
|
|
258
259
|
}
|
|
259
260
|
/**
|
|
260
261
|
* Render the given variation and its sub-variations, recursively.
|
|
@@ -441,10 +442,10 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
441
442
|
key: "renderComment",
|
|
442
443
|
value: function renderComment(node, comment, isVariation) {
|
|
443
444
|
var content;
|
|
445
|
+
var sanitizer = createSanitizer(true);
|
|
444
446
|
|
|
445
447
|
if (this.props.diagramVisible && comment.includes('[#]')) {
|
|
446
448
|
content = [];
|
|
447
|
-
var sanitizer = createSanitizer();
|
|
448
449
|
var isFirstPart = true;
|
|
449
450
|
|
|
450
451
|
var _iterator2 = _createForOfIteratorHelper(comment.split('[#]').entries()),
|
|
@@ -491,7 +492,7 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
491
492
|
_iterator2.f();
|
|
492
493
|
}
|
|
493
494
|
} else {
|
|
494
|
-
content = sanitizeHtml(comment);
|
|
495
|
+
content = sanitizeHtml(comment, sanitizer);
|
|
495
496
|
}
|
|
496
497
|
|
|
497
498
|
var key = isVariation ? 'initial-comment' : node.fullMoveNumber() + node.moveColor() + '-comment';
|
|
@@ -564,40 +565,6 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
|
|
|
564
565
|
this.props.onMoveSelected(nodeId === this.props.selection ? undefined : nodeId, 'click');
|
|
565
566
|
}
|
|
566
567
|
}
|
|
567
|
-
/**
|
|
568
|
-
* Return the square at the given location.
|
|
569
|
-
*/
|
|
570
|
-
|
|
571
|
-
}, {
|
|
572
|
-
key: "getNotationTextBuilder",
|
|
573
|
-
value: function getNotationTextBuilder() {
|
|
574
|
-
var pieceSymbols = this.props.pieceSymbols;
|
|
575
|
-
|
|
576
|
-
if (pieceSymbols === 'localized') {
|
|
577
|
-
var mapping = _i18n["default"].PIECE_SYMBOLS;
|
|
578
|
-
return function (notation) {
|
|
579
|
-
return notation.replace(/[KQRBNP]/g, function (match) {
|
|
580
|
-
return mapping[match];
|
|
581
|
-
});
|
|
582
|
-
};
|
|
583
|
-
} else if (pieceSymbols === 'figurines') {
|
|
584
|
-
return function (notation) {
|
|
585
|
-
return figurineNotation(notation, 'alpha');
|
|
586
|
-
};
|
|
587
|
-
} else if (pieceSymbols !== 'native' && pieceSymbols && ['K', 'Q', 'R', 'B', 'N', 'P'].every(function (p) {
|
|
588
|
-
return typeof pieceSymbols[p] === 'string';
|
|
589
|
-
})) {
|
|
590
|
-
return function (notation) {
|
|
591
|
-
return notation.replace(/[KQRBNP]/g, function (match) {
|
|
592
|
-
return pieceSymbols[match];
|
|
593
|
-
});
|
|
594
|
-
};
|
|
595
|
-
} else {
|
|
596
|
-
return function (notation) {
|
|
597
|
-
return notation;
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
568
|
/**
|
|
602
569
|
* Set the focus to the current component.
|
|
603
570
|
*
|
|
@@ -846,58 +813,50 @@ function formatResult(result) {
|
|
|
846
813
|
}
|
|
847
814
|
}
|
|
848
815
|
|
|
849
|
-
function createSanitizer() {
|
|
816
|
+
function createSanitizer(withBlockTags) {
|
|
817
|
+
var allowedTags = ['span', // general purpose
|
|
818
|
+
'a', // links
|
|
819
|
+
'b', 'strong', 'i', 'em', // bold, italic
|
|
820
|
+
'del', 'ins', 's', 'u', // underline, strikethrough
|
|
821
|
+
'sub', 'sup', // subscript, superscript
|
|
822
|
+
'abbr', // acronym (typically associated to a title=".." tooltip)
|
|
823
|
+
'q', 'cite', // quotation and title of a work
|
|
824
|
+
'mark', // highlighted text
|
|
825
|
+
'small' // smaller text
|
|
826
|
+
];
|
|
827
|
+
var allowedAttributes = {
|
|
828
|
+
'*': ['class', 'id', 'title'],
|
|
829
|
+
'a': ['href', 'target']
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
if (withBlockTags) {
|
|
833
|
+
allowedTags = allowedTags.concat(['div', // general purpose
|
|
834
|
+
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', // headings
|
|
835
|
+
'p', 'br', // paragraph and line break
|
|
836
|
+
'blockquote', // long quotation
|
|
837
|
+
'img', // image
|
|
838
|
+
'pre', // preformatted text
|
|
839
|
+
'ul', 'ol', 'li' // lists
|
|
840
|
+
]);
|
|
841
|
+
Object.assign(allowedAttributes, {
|
|
842
|
+
'img': ['alt', 'src', 'height', 'width']
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
|
|
850
846
|
return new _HtmlSanitizer["default"]({
|
|
851
|
-
allowedTags:
|
|
852
|
-
allowedAttributes:
|
|
853
|
-
'*': ['class', 'id', 'title'],
|
|
854
|
-
'a': ['href', 'target']
|
|
855
|
-
}
|
|
847
|
+
allowedTags: allowedTags,
|
|
848
|
+
allowedAttributes: allowedAttributes
|
|
856
849
|
});
|
|
857
850
|
}
|
|
858
851
|
|
|
859
852
|
function sanitizeHtml(text, sanitizer) {
|
|
860
853
|
if (!sanitizer) {
|
|
861
|
-
sanitizer = createSanitizer();
|
|
854
|
+
sanitizer = createSanitizer(false);
|
|
862
855
|
}
|
|
863
856
|
|
|
864
857
|
var result = sanitizer.parse(text);
|
|
865
858
|
return result !== null && result !== void 0 ? result : text;
|
|
866
859
|
}
|
|
867
|
-
/**
|
|
868
|
-
* Decompose the given string into piece symbol characters and sections of non piece symbol characters, and transform the piece symbols into
|
|
869
|
-
* React objects represented with the given chess font.
|
|
870
|
-
*/
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
function figurineNotation(text, fontName) {
|
|
874
|
-
var result = [];
|
|
875
|
-
var beginOfText = 0;
|
|
876
|
-
var pieceSymbolIndex = 0;
|
|
877
|
-
|
|
878
|
-
for (var pos = 0; pos < text.length; ++pos) {
|
|
879
|
-
var currentChar = text.charAt(pos);
|
|
880
|
-
|
|
881
|
-
if (currentChar === 'K' || currentChar === 'Q' || currentChar === 'R' || currentChar === 'B' || currentChar === 'N' || currentChar === 'P') {
|
|
882
|
-
if (pos > beginOfText) {
|
|
883
|
-
result.push(text.substring(beginOfText, pos));
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
beginOfText = pos + 1;
|
|
887
|
-
var key = 'symbol-' + pieceSymbolIndex++;
|
|
888
|
-
result.push( /*#__PURE__*/_react["default"].createElement("span", {
|
|
889
|
-
className: 'kokopu-font-' + fontName,
|
|
890
|
-
key: key
|
|
891
|
-
}, currentChar));
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
if (beginOfText < text.length) {
|
|
896
|
-
result.push(text.substring(beginOfText));
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
return result;
|
|
900
|
-
}
|
|
901
860
|
/**
|
|
902
861
|
* Try to interpret the given object as a chess game.
|
|
903
862
|
*/
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.formatMove = formatMove;
|
|
7
|
+
exports.moveFormatter = moveFormatter;
|
|
8
|
+
|
|
9
|
+
var _react = _interopRequireDefault(require("react"));
|
|
10
|
+
|
|
11
|
+
var _i18n = _interopRequireDefault(require("./i18n"));
|
|
12
|
+
|
|
13
|
+
require("./css/fonts.css");
|
|
14
|
+
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
16
|
+
|
|
17
|
+
/******************************************************************************
|
|
18
|
+
* *
|
|
19
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
20
|
+
* Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
|
|
21
|
+
* *
|
|
22
|
+
* This program is free software: you can redistribute it and/or *
|
|
23
|
+
* modify it under the terms of the GNU Lesser General Public License *
|
|
24
|
+
* as published by the Free Software Foundation, either version 3 of *
|
|
25
|
+
* the License, or (at your option) any later version. *
|
|
26
|
+
* *
|
|
27
|
+
* This program is distributed in the hope that it will be useful, *
|
|
28
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
29
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
30
|
+
* GNU Lesser General Public License for more details. *
|
|
31
|
+
* *
|
|
32
|
+
* You should have received a copy of the GNU Lesser General *
|
|
33
|
+
* Public License along with this program. If not, see *
|
|
34
|
+
* <http://www.gnu.org/licenses/>. *
|
|
35
|
+
* *
|
|
36
|
+
******************************************************************************/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Render the given SAN notation according to the given piece symbol style.
|
|
40
|
+
*
|
|
41
|
+
* @param {string|object} pieceSymbols See {@link moveFormatter}.
|
|
42
|
+
* @param {string} notation SAN notation.
|
|
43
|
+
* @returns {string|React.ReactFragment}
|
|
44
|
+
*/
|
|
45
|
+
function formatMove(pieceSymbols, notation) {
|
|
46
|
+
var formatter = moveFormatter(pieceSymbols);
|
|
47
|
+
return formatter(notation);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Return a callback capable of rendering a SAN notation using the given piece symbol style.
|
|
51
|
+
*
|
|
52
|
+
* @param {string|object} pieceSymbols `'native'`, `'localized'`, `'figurines'`, or an object defining a string-valued properties
|
|
53
|
+
* for each English piece symbol.
|
|
54
|
+
* @returns {function(string)} Callback returning either a string or a React fragment.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
function moveFormatter(pieceSymbols) {
|
|
59
|
+
if (pieceSymbols === 'localized') {
|
|
60
|
+
var mapping = _i18n["default"].PIECE_SYMBOLS;
|
|
61
|
+
return function (notation) {
|
|
62
|
+
return notation.replace(/[KQRBNP]/g, function (match) {
|
|
63
|
+
return mapping[match];
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
} else if (pieceSymbols === 'figurines') {
|
|
67
|
+
return function (notation) {
|
|
68
|
+
return figurineNotation('alpha', notation);
|
|
69
|
+
};
|
|
70
|
+
} else if (pieceSymbols !== 'native' && pieceSymbols && ['K', 'Q', 'R', 'B', 'N', 'P'].every(function (p) {
|
|
71
|
+
return typeof pieceSymbols[p] === 'string';
|
|
72
|
+
})) {
|
|
73
|
+
return function (notation) {
|
|
74
|
+
return notation.replace(/[KQRBNP]/g, function (match) {
|
|
75
|
+
return pieceSymbols[match];
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
} else {
|
|
79
|
+
return function (notation) {
|
|
80
|
+
return notation;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Decompose the given string into piece symbol characters and sections of non piece symbol characters, and transform the piece symbols into
|
|
86
|
+
* React objects represented with the given chess font.
|
|
87
|
+
*
|
|
88
|
+
* @ignore
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
function figurineNotation(fontName, text) {
|
|
93
|
+
var result = [];
|
|
94
|
+
var beginOfText = 0;
|
|
95
|
+
var pieceSymbolIndex = 0;
|
|
96
|
+
|
|
97
|
+
for (var pos = 0; pos < text.length; ++pos) {
|
|
98
|
+
var currentChar = text.charAt(pos);
|
|
99
|
+
|
|
100
|
+
if (currentChar === 'K' || currentChar === 'Q' || currentChar === 'R' || currentChar === 'B' || currentChar === 'N' || currentChar === 'P') {
|
|
101
|
+
if (pos > beginOfText) {
|
|
102
|
+
result.push(text.substring(beginOfText, pos));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
beginOfText = pos + 1;
|
|
106
|
+
var key = 'symbol-' + pieceSymbolIndex++;
|
|
107
|
+
result.push( /*#__PURE__*/_react["default"].createElement("span", {
|
|
108
|
+
className: 'kokopu-font-' + fontName,
|
|
109
|
+
key: key
|
|
110
|
+
}, currentChar));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (beginOfText < text.length) {
|
|
115
|
+
result.push(text.substring(beginOfText));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, result);
|
|
119
|
+
}
|
|
@@ -35,9 +35,14 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
|
|
|
35
35
|
|
|
36
36
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Those tags cannot have any children.
|
|
40
|
+
*/
|
|
41
|
+
var NO_CHILDREN_TAGS = new Set(['br', 'hr', 'img']);
|
|
38
42
|
/**
|
|
39
43
|
* HTML sanitizer: parse HTML string, keeping only the allowed HTML nodes, and the corresponding React object.
|
|
40
44
|
*/
|
|
45
|
+
|
|
41
46
|
var HtmlSanitizer = /*#__PURE__*/function () {
|
|
42
47
|
function HtmlSanitizer(_ref) {
|
|
43
48
|
var allowedTags = _ref.allowedTags,
|
|
@@ -101,7 +106,7 @@ var HtmlSanitizer = /*#__PURE__*/function () {
|
|
|
101
106
|
if (node.type === 'text') {
|
|
102
107
|
return node.data;
|
|
103
108
|
} else if (node.type === 'tag') {
|
|
104
|
-
var children = node.children.map(function (child) {
|
|
109
|
+
var children = NO_CHILDREN_TAGS.has(node.name) ? undefined : node.children.map(function (child) {
|
|
105
110
|
return _this2._processNode(child);
|
|
106
111
|
});
|
|
107
112
|
|
|
@@ -111,9 +116,9 @@ var HtmlSanitizer = /*#__PURE__*/function () {
|
|
|
111
116
|
attributes['key'] = this._allocateKey();
|
|
112
117
|
return /*#__PURE__*/_react["default"].createElement(node.name, attributes, children);
|
|
113
118
|
} else {
|
|
114
|
-
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
|
|
119
|
+
return children ? /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
|
|
115
120
|
key: this._allocateKey()
|
|
116
|
-
}, children);
|
|
121
|
+
}, children) : undefined;
|
|
117
122
|
}
|
|
118
123
|
} else {
|
|
119
124
|
return undefined;
|
package/dist/lib/index.js
CHANGED
|
@@ -57,12 +57,24 @@ Object.defineProperty(exports, "flattenTextMarkers", {
|
|
|
57
57
|
return _markers.flattenTextMarkers;
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
|
+
Object.defineProperty(exports, "formatMove", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function get() {
|
|
63
|
+
return _formatmove.formatMove;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
60
66
|
Object.defineProperty(exports, "i18n", {
|
|
61
67
|
enumerable: true,
|
|
62
68
|
get: function get() {
|
|
63
69
|
return _i18n["default"];
|
|
64
70
|
}
|
|
65
71
|
});
|
|
72
|
+
Object.defineProperty(exports, "moveFormatter", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function get() {
|
|
75
|
+
return _formatmove.moveFormatter;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
66
78
|
Object.defineProperty(exports, "parseArrowMarkers", {
|
|
67
79
|
enumerable: true,
|
|
68
80
|
get: function get() {
|
|
@@ -84,6 +96,8 @@ Object.defineProperty(exports, "parseTextMarkers", {
|
|
|
84
96
|
|
|
85
97
|
var _markers = require("./markers");
|
|
86
98
|
|
|
99
|
+
var _formatmove = require("./formatmove");
|
|
100
|
+
|
|
87
101
|
var _i18n = _interopRequireDefault(require("./i18n"));
|
|
88
102
|
|
|
89
103
|
var _Chessboard = _interopRequireDefault(require("./Chessboard"));
|
|
@@ -85,7 +85,7 @@ probably to assure himself that the combination was sound and that he had a forc
|
|
|
85
85
|
[Date "????.??.??"]
|
|
86
86
|
[Round "<strong>3</strong>.2"]
|
|
87
87
|
[White "1<sup>st</sup> <em>player</em>"]
|
|
88
|
-
[Black "2<sub>nd</sub> <
|
|
88
|
+
[Black "2<sub>nd</sub> <i>player</i>"]
|
|
89
89
|
[Result "*"]
|
|
90
90
|
[WhiteElo "<ins>2800</ins>"]
|
|
91
91
|
[BlackElo "<del>1010</del>"]
|
|
@@ -104,7 +104,13 @@ 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
|
|
107
|
+
{I'm a <strong><ins>comment</ins></strong> with some <em class="myClass">HTML content</em> in it.<br/>
|
|
108
|
+
Lists are supported:
|
|
109
|
+
<ul>
|
|
110
|
+
<li>1<sup>st</sup> point</li>
|
|
111
|
+
<li>2<sup>nd</sup> point</li>
|
|
112
|
+
</ul>
|
|
113
|
+
... and so are images: <img src="../smiley.png" alt="smiley" />}
|
|
108
114
|
|
|
109
115
|
*
|
|
110
116
|
|
|
@@ -119,9 +125,9 @@ probably to assure himself that the combination was sound and that he had a forc
|
|
|
119
125
|
[Result "*"]
|
|
120
126
|
|
|
121
127
|
{
|
|
122
|
-
Using <
|
|
123
|
-
... but <
|
|
124
|
-
Using <span style="color: cyan;">style attributes</span> is not allowed
|
|
128
|
+
Using <form class="myClass">form-related tags</form> is not allowed.<br/>
|
|
129
|
+
... but <button class="myClass"><em>legit HTML elements</em> within forbidden HTML tags</button> are rendered.<br/>
|
|
130
|
+
Using <span style="color: cyan;">style attributes</span> is not allowed.<br/>
|
|
125
131
|
Using scripts is not allowed. <script>alert('You should not see this either.');</script>
|
|
126
132
|
}
|
|
127
133
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kokopu-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A React-based library to create and display chessboard and chess-related components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chess",
|
|
@@ -38,19 +38,19 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@babel/cli": "^7.17.10",
|
|
41
|
-
"@babel/core": "^7.
|
|
42
|
-
"@babel/preset-env": "^7.
|
|
41
|
+
"@babel/core": "^7.18.2",
|
|
42
|
+
"@babel/preset-env": "^7.18.2",
|
|
43
43
|
"@babel/preset-react": "^7.17.12",
|
|
44
44
|
"@emotion/react": "^11.9.0",
|
|
45
45
|
"@emotion/styled": "^11.8.1",
|
|
46
|
-
"@mui/material": "^5.8.
|
|
46
|
+
"@mui/material": "^5.8.2",
|
|
47
47
|
"babel-loader": "^8.2.5",
|
|
48
48
|
"babel-plugin-istanbul": "^6.1.1",
|
|
49
49
|
"copy-webpack-plugin": "^11.0.0",
|
|
50
50
|
"coveralls": "^3.1.1",
|
|
51
51
|
"css-loader": "^6.7.1",
|
|
52
|
-
"eslint": "^8.
|
|
53
|
-
"eslint-plugin-react": "^7.
|
|
52
|
+
"eslint": "^8.16.0",
|
|
53
|
+
"eslint-plugin-react": "^7.30.0",
|
|
54
54
|
"html-webpack-plugin": "^5.5.0",
|
|
55
55
|
"img-diff-js": "^0.5.2",
|
|
56
56
|
"mocha": "^10.0.0",
|
|
@@ -39,7 +39,10 @@ var plugins = items.map(item => new HtmlWebpackPlugin({
|
|
|
39
39
|
filename: item + '/index.html',
|
|
40
40
|
}));
|
|
41
41
|
plugins.push(new CopyWebpackPlugin({
|
|
42
|
-
patterns: [
|
|
42
|
+
patterns: [
|
|
43
|
+
{ from: './graphic_test_app/common/heartbeat.txt', to: 'heartbeat.txt' },
|
|
44
|
+
{ from: './graphic_test_app/common/smiley.png', to: 'smiley.png' },
|
|
45
|
+
],
|
|
43
46
|
}));
|
|
44
47
|
|
|
45
48
|
module.exports = {
|
package/src/Movetext.js
CHANGED
|
@@ -27,9 +27,9 @@ import kokopu from 'kokopu';
|
|
|
27
27
|
import HtmlSanitizer from './impl/HtmlSanitizer';
|
|
28
28
|
import Chessboard from './Chessboard';
|
|
29
29
|
import ErrorBox from './ErrorBox';
|
|
30
|
+
import { moveFormatter } from './formatmove';
|
|
30
31
|
import i18n from './i18n';
|
|
31
32
|
|
|
32
|
-
import './css/fonts.css';
|
|
33
33
|
import './css/movetext.css';
|
|
34
34
|
|
|
35
35
|
|
|
@@ -144,7 +144,8 @@ export default class Movetext extends React.Component {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
renderBody(game) {
|
|
147
|
-
|
|
147
|
+
let notationTextBuilder = moveFormatter(this.props.pieceSymbols);
|
|
148
|
+
return this.renderVariation(notationTextBuilder, game.mainVariation(), 'main-variation', true, game.result());
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
/**
|
|
@@ -284,9 +285,9 @@ export default class Movetext extends React.Component {
|
|
|
284
285
|
*/
|
|
285
286
|
renderComment(node, comment, isVariation) {
|
|
286
287
|
let content;
|
|
288
|
+
let sanitizer = createSanitizer(true);
|
|
287
289
|
if (this.props.diagramVisible && comment.includes('[#]')) {
|
|
288
290
|
content = [];
|
|
289
|
-
let sanitizer = createSanitizer();
|
|
290
291
|
let isFirstPart = true;
|
|
291
292
|
for (let [index, part] of comment.split('[#]').entries()) {
|
|
292
293
|
if (!isFirstPart) {
|
|
@@ -309,7 +310,7 @@ export default class Movetext extends React.Component {
|
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
312
|
else {
|
|
312
|
-
content = sanitizeHtml(comment);
|
|
313
|
+
content = sanitizeHtml(comment, sanitizer);
|
|
313
314
|
}
|
|
314
315
|
let key = isVariation ? 'initial-comment' : node.fullMoveNumber() + node.moveColor() + '-comment';
|
|
315
316
|
return node.isLongComment() ? <div className="kokopu-comment" key={key}>{content}</div> : <span className="kokopu-comment" key={key}>{content}</span>;
|
|
@@ -368,26 +369,6 @@ export default class Movetext extends React.Component {
|
|
|
368
369
|
}
|
|
369
370
|
}
|
|
370
371
|
|
|
371
|
-
/**
|
|
372
|
-
* Return the square at the given location.
|
|
373
|
-
*/
|
|
374
|
-
getNotationTextBuilder() {
|
|
375
|
-
let pieceSymbols = this.props.pieceSymbols;
|
|
376
|
-
if (pieceSymbols === 'localized') {
|
|
377
|
-
let mapping = i18n.PIECE_SYMBOLS;
|
|
378
|
-
return notation => notation.replace(/[KQRBNP]/g, match => mapping[match]);
|
|
379
|
-
}
|
|
380
|
-
else if (pieceSymbols === 'figurines') {
|
|
381
|
-
return notation => figurineNotation(notation, 'alpha');
|
|
382
|
-
}
|
|
383
|
-
else if (pieceSymbols !== 'native' && pieceSymbols && ['K', 'Q', 'R', 'B', 'N', 'P'].every(p => typeof pieceSymbols[p] === 'string')) {
|
|
384
|
-
return notation => notation.replace(/[KQRBNP]/g, match => pieceSymbols[match]);
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
return notation => notation;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
372
|
/**
|
|
392
373
|
* Set the focus to the current component.
|
|
393
374
|
*
|
|
@@ -615,52 +596,49 @@ function formatResult(result) {
|
|
|
615
596
|
}
|
|
616
597
|
|
|
617
598
|
|
|
618
|
-
function createSanitizer() {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
599
|
+
function createSanitizer(withBlockTags) {
|
|
600
|
+
let allowedTags = [
|
|
601
|
+
'span', // general purpose
|
|
602
|
+
'a', // links
|
|
603
|
+
'b', 'strong', 'i', 'em', // bold, italic
|
|
604
|
+
'del', 'ins', 's', 'u', // underline, strikethrough
|
|
605
|
+
'sub', 'sup', // subscript, superscript
|
|
606
|
+
'abbr', // acronym (typically associated to a title=".." tooltip)
|
|
607
|
+
'q', 'cite', // quotation and title of a work
|
|
608
|
+
'mark', // highlighted text
|
|
609
|
+
'small', // smaller text
|
|
610
|
+
];
|
|
611
|
+
let allowedAttributes = {
|
|
612
|
+
'*': [ 'class', 'id', 'title' ],
|
|
613
|
+
'a': [ 'href', 'target' ],
|
|
614
|
+
};
|
|
615
|
+
if (withBlockTags) {
|
|
616
|
+
allowedTags = allowedTags.concat([
|
|
617
|
+
'div', // general purpose
|
|
618
|
+
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', // headings
|
|
619
|
+
'p', 'br', // paragraph and line break
|
|
620
|
+
'blockquote', // long quotation
|
|
621
|
+
'img', // image
|
|
622
|
+
'pre', // preformatted text
|
|
623
|
+
'ul', 'ol', 'li', // lists
|
|
624
|
+
]);
|
|
625
|
+
Object.assign(allowedAttributes, {
|
|
626
|
+
'img': [ 'alt', 'src', 'height', 'width' ],
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
return new HtmlSanitizer({ allowedTags: allowedTags, allowedAttributes: allowedAttributes });
|
|
626
630
|
}
|
|
627
631
|
|
|
628
632
|
|
|
629
633
|
function sanitizeHtml(text, sanitizer) {
|
|
630
634
|
if (!sanitizer) {
|
|
631
|
-
sanitizer = createSanitizer();
|
|
635
|
+
sanitizer = createSanitizer(false);
|
|
632
636
|
}
|
|
633
637
|
let result = sanitizer.parse(text);
|
|
634
638
|
return result ?? text;
|
|
635
639
|
}
|
|
636
640
|
|
|
637
641
|
|
|
638
|
-
/**
|
|
639
|
-
* Decompose the given string into piece symbol characters and sections of non piece symbol characters, and transform the piece symbols into
|
|
640
|
-
* React objects represented with the given chess font.
|
|
641
|
-
*/
|
|
642
|
-
function figurineNotation(text, fontName) {
|
|
643
|
-
let result = [];
|
|
644
|
-
let beginOfText = 0;
|
|
645
|
-
let pieceSymbolIndex = 0;
|
|
646
|
-
for (let pos = 0; pos < text.length; ++pos) {
|
|
647
|
-
let currentChar = text.charAt(pos);
|
|
648
|
-
if (currentChar === 'K' || currentChar === 'Q' || currentChar === 'R' || currentChar === 'B' || currentChar === 'N' || currentChar === 'P') {
|
|
649
|
-
if (pos > beginOfText) {
|
|
650
|
-
result.push(text.substring(beginOfText, pos));
|
|
651
|
-
}
|
|
652
|
-
beginOfText = pos + 1;
|
|
653
|
-
let key = 'symbol-' + (pieceSymbolIndex++);
|
|
654
|
-
result.push(<span className={'kokopu-font-' + fontName} key={key}>{currentChar}</span>);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
if (beginOfText < text.length) {
|
|
658
|
-
result.push(text.substring(beginOfText));
|
|
659
|
-
}
|
|
660
|
-
return result;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
|
|
664
642
|
/**
|
|
665
643
|
* Try to interpret the given object as a chess game.
|
|
666
644
|
*/
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
4
|
+
* Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
|
|
5
|
+
* *
|
|
6
|
+
* This program is free software: you can redistribute it and/or *
|
|
7
|
+
* modify it under the terms of the GNU Lesser General Public License *
|
|
8
|
+
* as published by the Free Software Foundation, either version 3 of *
|
|
9
|
+
* the License, or (at your option) any later version. *
|
|
10
|
+
* *
|
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
14
|
+
* GNU Lesser General Public License for more details. *
|
|
15
|
+
* *
|
|
16
|
+
* You should have received a copy of the GNU Lesser General *
|
|
17
|
+
* Public License along with this program. If not, see *
|
|
18
|
+
* <http://www.gnu.org/licenses/>. *
|
|
19
|
+
* *
|
|
20
|
+
******************************************************************************/
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
import React from 'react';
|
|
24
|
+
import i18n from './i18n';
|
|
25
|
+
|
|
26
|
+
import './css/fonts.css';
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Render the given SAN notation according to the given piece symbol style.
|
|
31
|
+
*
|
|
32
|
+
* @param {string|object} pieceSymbols See {@link moveFormatter}.
|
|
33
|
+
* @param {string} notation SAN notation.
|
|
34
|
+
* @returns {string|React.ReactFragment}
|
|
35
|
+
*/
|
|
36
|
+
export function formatMove(pieceSymbols, notation) {
|
|
37
|
+
let formatter = moveFormatter(pieceSymbols);
|
|
38
|
+
return formatter(notation);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Return a callback capable of rendering a SAN notation using the given piece symbol style.
|
|
44
|
+
*
|
|
45
|
+
* @param {string|object} pieceSymbols `'native'`, `'localized'`, `'figurines'`, or an object defining a string-valued properties
|
|
46
|
+
* for each English piece symbol.
|
|
47
|
+
* @returns {function(string)} Callback returning either a string or a React fragment.
|
|
48
|
+
*/
|
|
49
|
+
export function moveFormatter(pieceSymbols) {
|
|
50
|
+
if (pieceSymbols === 'localized') {
|
|
51
|
+
let mapping = i18n.PIECE_SYMBOLS;
|
|
52
|
+
return notation => notation.replace(/[KQRBNP]/g, match => mapping[match]);
|
|
53
|
+
}
|
|
54
|
+
else if (pieceSymbols === 'figurines') {
|
|
55
|
+
return notation => figurineNotation('alpha', notation);
|
|
56
|
+
}
|
|
57
|
+
else if (pieceSymbols !== 'native' && pieceSymbols && ['K', 'Q', 'R', 'B', 'N', 'P'].every(p => typeof pieceSymbols[p] === 'string')) {
|
|
58
|
+
return notation => notation.replace(/[KQRBNP]/g, match => pieceSymbols[match]);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return notation => notation;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Decompose the given string into piece symbol characters and sections of non piece symbol characters, and transform the piece symbols into
|
|
68
|
+
* React objects represented with the given chess font.
|
|
69
|
+
*
|
|
70
|
+
* @ignore
|
|
71
|
+
*/
|
|
72
|
+
function figurineNotation(fontName, text) {
|
|
73
|
+
let result = [];
|
|
74
|
+
let beginOfText = 0;
|
|
75
|
+
let pieceSymbolIndex = 0;
|
|
76
|
+
for (let pos = 0; pos < text.length; ++pos) {
|
|
77
|
+
let currentChar = text.charAt(pos);
|
|
78
|
+
if (currentChar === 'K' || currentChar === 'Q' || currentChar === 'R' || currentChar === 'B' || currentChar === 'N' || currentChar === 'P') {
|
|
79
|
+
if (pos > beginOfText) {
|
|
80
|
+
result.push(text.substring(beginOfText, pos));
|
|
81
|
+
}
|
|
82
|
+
beginOfText = pos + 1;
|
|
83
|
+
let key = 'symbol-' + (pieceSymbolIndex++);
|
|
84
|
+
result.push(<span className={'kokopu-font-' + fontName} key={key}>{currentChar}</span>);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (beginOfText < text.length) {
|
|
88
|
+
result.push(text.substring(beginOfText));
|
|
89
|
+
}
|
|
90
|
+
return <>{result}</>;
|
|
91
|
+
}
|
|
@@ -24,6 +24,12 @@ import React from 'react';
|
|
|
24
24
|
import * as htmlparser2 from 'htmlparser2';
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Those tags cannot have any children.
|
|
29
|
+
*/
|
|
30
|
+
const NO_CHILDREN_TAGS = new Set([ 'br', 'hr', 'img' ]);
|
|
31
|
+
|
|
32
|
+
|
|
27
33
|
/**
|
|
28
34
|
* HTML sanitizer: parse HTML string, keeping only the allowed HTML nodes, and the corresponding React object.
|
|
29
35
|
*/
|
|
@@ -74,14 +80,14 @@ export default class HtmlSanitizer {
|
|
|
74
80
|
return node.data;
|
|
75
81
|
}
|
|
76
82
|
else if (node.type === 'tag') {
|
|
77
|
-
let children = node.children.map(child => this._processNode(child));
|
|
83
|
+
let children = NO_CHILDREN_TAGS.has(node.name) ? undefined : node.children.map(child => this._processNode(child));
|
|
78
84
|
if (this._allowedTags.has(node.name)) {
|
|
79
85
|
let attributes = this._filterAttributes(node.name, node.attribs);
|
|
80
86
|
attributes['key'] = this._allocateKey();
|
|
81
87
|
return React.createElement(node.name, attributes, children);
|
|
82
88
|
}
|
|
83
89
|
else {
|
|
84
|
-
return <React.Fragment key={this._allocateKey()}>{children}</React.Fragment
|
|
90
|
+
return children ? <React.Fragment key={this._allocateKey()}>{children}</React.Fragment> : undefined;
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
else {
|
package/src/index.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
export { flattenSquareMarkers, parseSquareMarkers, flattenTextMarkers, parseTextMarkers, flattenArrowMarkers, parseArrowMarkers } from './markers';
|
|
24
|
+
export { formatMove, moveFormatter } from './formatmove';
|
|
24
25
|
export { default as i18n } from './i18n';
|
|
25
26
|
export { default as Chessboard } from './Chessboard';
|
|
26
27
|
export { default as ErrorBox } from './ErrorBox';
|
|
Binary file
|
|
Binary file
|
|
Binary file
|