kokopu-react 1.3.1 → 1.4.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 +4 -0
- package/dist/lib/ArrowMarkerIcon.js +2 -4
- package/dist/lib/Chessboard.js +17 -25
- package/dist/lib/TextMarkerIcon.js +11 -10
- package/dist/lib/css/symbol.css +25 -0
- package/dist/lib/impl/ArrowTip.js +2 -7
- package/dist/lib/impl/TextSymbol.js +100 -0
- package/dist/lib/impl/util.js +5 -5
- package/dist/lib/index.js +24 -24
- package/dist/lib/markers.js +10 -10
- package/doc_src/demo/PageChessboardEdition.js +2 -1
- package/doc_src/theming/kokopu-react-favicon.png +0 -0
- package/graphic_test_app/01_marker_icons.js +5 -3
- package/graphic_test_app/04_chessboard_annotations.js +1 -1
- package/package.json +16 -16
- package/scripts/test_graphic/docker-compose.yml +1 -1
- package/scripts/test_graphic/webpack-config.js +1 -0
- package/scripts/test_headless.webpack-config.js +1 -0
- package/src/ArrowMarkerIcon.js +1 -1
- package/src/Chessboard.js +9 -8
- package/src/TextMarkerIcon.js +6 -6
- package/src/css/symbol.css +25 -0
- package/src/impl/ArrowTip.js +2 -6
- package/src/impl/TextSymbol.js +77 -0
- package/src/impl/util.js +1 -1
- package/src/markers.js +7 -6
- package/test/1_markers.js +19 -0
- package/test/3_marker_icons_graphic.js +1 -1
- package/test/references/01_marker_icons/10.png +0 -0
- package/test/references/01_marker_icons/9.png +0 -0
- package/test/references/04_chessboard_annotations/4.png +0 -0
- package/test/references/04_chessboard_annotations/5.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -85,10 +85,8 @@ var ArrowMarkerIcon = /*#__PURE__*/function (_React$Component) {
|
|
|
85
85
|
x2: size - halfThickness * 3,
|
|
86
86
|
y2: size / 2,
|
|
87
87
|
stroke: this.props.color,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
'markerEnd': "url(#".concat(this.arrowTipId, ")")
|
|
91
|
-
}
|
|
88
|
+
strokeWidth: halfThickness * 2,
|
|
89
|
+
markerEnd: "url(#".concat(this.arrowTipId, ")")
|
|
92
90
|
}));
|
|
93
91
|
}
|
|
94
92
|
}]);
|
package/dist/lib/Chessboard.js
CHANGED
|
@@ -21,6 +21,8 @@ var _piecesets2 = _interopRequireDefault(require("./impl/piecesets"));
|
|
|
21
21
|
|
|
22
22
|
var _ArrowTip = _interopRequireDefault(require("./impl/ArrowTip"));
|
|
23
23
|
|
|
24
|
+
var _TextSymbol = _interopRequireDefault(require("./impl/TextSymbol"));
|
|
25
|
+
|
|
24
26
|
var _ErrorBox = _interopRequireDefault(require("./ErrorBox"));
|
|
25
27
|
|
|
26
28
|
var _i18n = _interopRequireDefault(require("./i18n"));
|
|
@@ -408,10 +410,8 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
408
410
|
x2: xTo,
|
|
409
411
|
y2: yTo,
|
|
410
412
|
stroke: colorset[this.props.editedArrowColor],
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
'markerEnd': "url(#".concat(arrowTipId, ")")
|
|
414
|
-
}
|
|
413
|
+
strokeWidth: strokeWidth,
|
|
414
|
+
markerEnd: "url(#".concat(arrowTipId, ")")
|
|
415
415
|
});
|
|
416
416
|
}
|
|
417
417
|
}, {
|
|
@@ -567,16 +567,16 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
567
567
|
|
|
568
568
|
x += squareSize / 2;
|
|
569
569
|
y += squareSize / 2;
|
|
570
|
-
result.push( /*#__PURE__*/_react["default"].createElement("
|
|
570
|
+
result.push( /*#__PURE__*/_react["default"].createElement("g", {
|
|
571
571
|
key: 'txtm-' + sq,
|
|
572
|
-
className: "kokopu-annotation
|
|
572
|
+
className: "kokopu-annotation"
|
|
573
|
+
}, /*#__PURE__*/_react["default"].createElement(_TextSymbol["default"], {
|
|
573
574
|
x: x,
|
|
574
575
|
y: y,
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}, value.symbol));
|
|
576
|
+
size: squareSize,
|
|
577
|
+
symbol: value.symbol,
|
|
578
|
+
color: colorset[value.color]
|
|
579
|
+
})));
|
|
580
580
|
});
|
|
581
581
|
return result;
|
|
582
582
|
}
|
|
@@ -624,10 +624,8 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
624
624
|
x2: xTo,
|
|
625
625
|
y2: yTo,
|
|
626
626
|
stroke: colorset[color],
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
'markerEnd': "url(#".concat(arrowTipId, ")")
|
|
630
|
-
}
|
|
627
|
+
strokeWidth: strokeWidth,
|
|
628
|
+
markerEnd: "url(#".concat(arrowTipId, ")")
|
|
631
629
|
}));
|
|
632
630
|
});
|
|
633
631
|
return result;
|
|
@@ -663,10 +661,8 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
663
661
|
x2: x,
|
|
664
662
|
y2: y,
|
|
665
663
|
stroke: colorset['highlight'],
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
'markerEnd': "url(#".concat(this.getArrowTipId('highlight'), ")")
|
|
669
|
-
}
|
|
664
|
+
strokeWidth: squareSize * STROKE_THICKNESS_FACTOR,
|
|
665
|
+
markerEnd: "url(#".concat(this.getArrowTipId('highlight'), ")")
|
|
670
666
|
});
|
|
671
667
|
}
|
|
672
668
|
}, {
|
|
@@ -702,9 +698,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
702
698
|
className: "kokopu-coordinate kokopu-label",
|
|
703
699
|
x: x,
|
|
704
700
|
y: y,
|
|
705
|
-
|
|
706
|
-
'fontSize': fontSize
|
|
707
|
-
}
|
|
701
|
+
fontSize: fontSize
|
|
708
702
|
}, label);
|
|
709
703
|
}
|
|
710
704
|
}, {
|
|
@@ -718,9 +712,7 @@ var Chessboard = /*#__PURE__*/function (_React$Component) {
|
|
|
718
712
|
className: "kokopu-coordinate kokopu-label",
|
|
719
713
|
x: x,
|
|
720
714
|
y: y,
|
|
721
|
-
|
|
722
|
-
'fontSize': fontSize
|
|
723
|
-
}
|
|
715
|
+
fontSize: fontSize
|
|
724
716
|
}, label);
|
|
725
717
|
}
|
|
726
718
|
}, {
|
|
@@ -9,10 +9,10 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
9
9
|
|
|
10
10
|
var _react = _interopRequireDefault(require("react"));
|
|
11
11
|
|
|
12
|
-
require("./css/label.css");
|
|
13
|
-
|
|
14
12
|
var _util = require("./impl/util");
|
|
15
13
|
|
|
14
|
+
var _TextSymbol = _interopRequireDefault(require("./impl/TextSymbol"));
|
|
15
|
+
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
17
17
|
|
|
18
18
|
/******************************************************************************
|
|
@@ -52,15 +52,13 @@ function TextMarkerIcon(props) {
|
|
|
52
52
|
viewBox: viewBox,
|
|
53
53
|
width: size,
|
|
54
54
|
height: size
|
|
55
|
-
}, /*#__PURE__*/_react["default"].createElement("
|
|
56
|
-
className: "kokopu-label",
|
|
55
|
+
}, /*#__PURE__*/_react["default"].createElement(_TextSymbol["default"], {
|
|
57
56
|
x: size / 2,
|
|
58
57
|
y: size / 2,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}, props.symbol));
|
|
58
|
+
size: size,
|
|
59
|
+
symbol: props.symbol,
|
|
60
|
+
color: props.color
|
|
61
|
+
}));
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
TextMarkerIcon.propTypes = {
|
|
@@ -70,7 +68,10 @@ TextMarkerIcon.propTypes = {
|
|
|
70
68
|
size: _propTypes["default"].number.isRequired,
|
|
71
69
|
|
|
72
70
|
/**
|
|
73
|
-
* Symbol to represent on the icon. Must be
|
|
71
|
+
* Symbol to represent on the icon. Must be one of:
|
|
72
|
+
* - any letter from A to Z (either upper-case or lower-case),
|
|
73
|
+
* - any digit from 0 to 9,
|
|
74
|
+
* - any symbol code among `'plus'`, `'times'`, `'dot'`, or `'circle'`.
|
|
74
75
|
*/
|
|
75
76
|
symbol: _propTypes["default"].string.isRequired,
|
|
76
77
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
4
|
+
* Copyright (C) 2021 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
|
+
.kokopu-symbolCircle {
|
|
24
|
+
fill: transparent;
|
|
25
|
+
}
|
|
@@ -43,9 +43,7 @@ function ArrowTip(props) {
|
|
|
43
43
|
refX: 2.5,
|
|
44
44
|
refY: 2,
|
|
45
45
|
orient: "auto",
|
|
46
|
-
|
|
47
|
-
fill: props.color
|
|
48
|
-
}
|
|
46
|
+
fill: props.color
|
|
49
47
|
}, /*#__PURE__*/_react["default"].createElement("path", {
|
|
50
48
|
d: "M 4,2 L 0,4 L 1,2 L 0,0 Z"
|
|
51
49
|
}));
|
|
@@ -60,8 +58,5 @@ ArrowTip.propTypes = {
|
|
|
60
58
|
/**
|
|
61
59
|
* Color to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
|
|
62
60
|
*/
|
|
63
|
-
color: _propTypes["default"].string
|
|
64
|
-
};
|
|
65
|
-
ArrowTip.defaultProps = {
|
|
66
|
-
color: 'currentcolor'
|
|
61
|
+
color: _propTypes["default"].string.isRequired
|
|
67
62
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = TextSymbol;
|
|
7
|
+
|
|
8
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
|
+
|
|
10
|
+
var _react = _interopRequireDefault(require("react"));
|
|
11
|
+
|
|
12
|
+
require("../css/label.css");
|
|
13
|
+
|
|
14
|
+
require("../css/symbol.css");
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
17
|
+
|
|
18
|
+
/******************************************************************************
|
|
19
|
+
* *
|
|
20
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
21
|
+
* Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
|
|
22
|
+
* *
|
|
23
|
+
* This program is free software: you can redistribute it and/or *
|
|
24
|
+
* modify it under the terms of the GNU Lesser General Public License *
|
|
25
|
+
* as published by the Free Software Foundation, either version 3 of *
|
|
26
|
+
* the License, or (at your option) any later version. *
|
|
27
|
+
* *
|
|
28
|
+
* This program is distributed in the hope that it will be useful, *
|
|
29
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
30
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
31
|
+
* GNU Lesser General Public License for more details. *
|
|
32
|
+
* *
|
|
33
|
+
* You should have received a copy of the GNU Lesser General *
|
|
34
|
+
* Public License along with this program. If not, see *
|
|
35
|
+
* <http://www.gnu.org/licenses/>. *
|
|
36
|
+
* *
|
|
37
|
+
******************************************************************************/
|
|
38
|
+
var SHAPE_THICKNESS_FACTOR = 0.1;
|
|
39
|
+
var DOT_RADIUS_FACTOR = 0.15;
|
|
40
|
+
var CIRCLE_RADIUS_FACTOR = 0.425;
|
|
41
|
+
/**
|
|
42
|
+
* Symbol of a text marker.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
function TextSymbol(props) {
|
|
46
|
+
if (props.symbol === 'dot') {
|
|
47
|
+
return /*#__PURE__*/_react["default"].createElement("circle", {
|
|
48
|
+
cx: props.x,
|
|
49
|
+
cy: props.y,
|
|
50
|
+
r: props.size * DOT_RADIUS_FACTOR,
|
|
51
|
+
fill: props.color
|
|
52
|
+
});
|
|
53
|
+
} else if (props.symbol === 'circle') {
|
|
54
|
+
var thickness = props.size * SHAPE_THICKNESS_FACTOR;
|
|
55
|
+
return /*#__PURE__*/_react["default"].createElement("circle", {
|
|
56
|
+
className: "kokopu-symbolCircle",
|
|
57
|
+
cx: props.x,
|
|
58
|
+
cy: props.y,
|
|
59
|
+
r: props.size * CIRCLE_RADIUS_FACTOR,
|
|
60
|
+
stroke: props.color,
|
|
61
|
+
strokeWidth: thickness
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
var symbol = props.symbol === 'plus' ? '+' : props.symbol === 'times' ? "\xD7" : props.symbol;
|
|
65
|
+
return /*#__PURE__*/_react["default"].createElement("text", {
|
|
66
|
+
className: "kokopu-label",
|
|
67
|
+
x: props.x,
|
|
68
|
+
y: props.y,
|
|
69
|
+
fill: props.color,
|
|
70
|
+
fontSize: props.size
|
|
71
|
+
}, symbol);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
TextSymbol.propTypes = {
|
|
76
|
+
/**
|
|
77
|
+
* X-coordinate of the center of the symbol.
|
|
78
|
+
*/
|
|
79
|
+
x: _propTypes["default"].number.isRequired,
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Y-coordinate of the center of the symbol.
|
|
83
|
+
*/
|
|
84
|
+
y: _propTypes["default"].number.isRequired,
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Size of the symbol (i.e. size of square in which the symbol is rendered).
|
|
88
|
+
*/
|
|
89
|
+
size: _propTypes["default"].number.isRequired,
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Symbol code.
|
|
93
|
+
*/
|
|
94
|
+
symbol: _propTypes["default"].string.isRequired,
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Color to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
|
|
98
|
+
*/
|
|
99
|
+
color: _propTypes["default"].string.isRequired
|
|
100
|
+
};
|
package/dist/lib/impl/util.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.MIN_SQUARE_SIZE = exports.MAX_SQUARE_SIZE = void 0;
|
|
6
7
|
exports.generateRandomId = generateRandomId;
|
|
7
|
-
exports.sanitizeInteger = sanitizeInteger;
|
|
8
|
-
exports.isValidSquare = isValidSquare;
|
|
9
|
-
exports.isValidVector = isValidVector;
|
|
10
8
|
exports.isValidColor = isValidColor;
|
|
9
|
+
exports.isValidSquare = isValidSquare;
|
|
11
10
|
exports.isValidSymbol = isValidSymbol;
|
|
12
|
-
exports.
|
|
11
|
+
exports.isValidVector = isValidVector;
|
|
12
|
+
exports.sanitizeInteger = sanitizeInteger;
|
|
13
13
|
|
|
14
14
|
/******************************************************************************
|
|
15
15
|
* *
|
|
@@ -65,5 +65,5 @@ function isValidColor(color) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function isValidSymbol(symbol) {
|
|
68
|
-
return /^[A-Za-z0-9]$/.test(symbol);
|
|
68
|
+
return /^(?:[A-Za-z0-9]|plus|times|dot|circle)$/.test(symbol);
|
|
69
69
|
}
|
package/dist/lib/index.js
CHANGED
|
@@ -3,76 +3,76 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
Object.defineProperty(exports, "
|
|
6
|
+
Object.defineProperty(exports, "ArrowMarkerIcon", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function get() {
|
|
9
|
-
return
|
|
9
|
+
return _ArrowMarkerIcon["default"];
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "Chessboard", {
|
|
13
13
|
enumerable: true,
|
|
14
14
|
get: function get() {
|
|
15
|
-
return
|
|
15
|
+
return _Chessboard["default"];
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
-
Object.defineProperty(exports, "
|
|
18
|
+
Object.defineProperty(exports, "ErrorBox", {
|
|
19
19
|
enumerable: true,
|
|
20
20
|
get: function get() {
|
|
21
|
-
return
|
|
21
|
+
return _ErrorBox["default"];
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
-
Object.defineProperty(exports, "
|
|
24
|
+
Object.defineProperty(exports, "SquareMarkerIcon", {
|
|
25
25
|
enumerable: true,
|
|
26
26
|
get: function get() {
|
|
27
|
-
return
|
|
27
|
+
return _SquareMarkerIcon["default"];
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
Object.defineProperty(exports, "
|
|
30
|
+
Object.defineProperty(exports, "TextMarkerIcon", {
|
|
31
31
|
enumerable: true,
|
|
32
32
|
get: function get() {
|
|
33
|
-
return
|
|
33
|
+
return _TextMarkerIcon["default"];
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
|
-
Object.defineProperty(exports, "
|
|
36
|
+
Object.defineProperty(exports, "flattenArrowMarkers", {
|
|
37
37
|
enumerable: true,
|
|
38
38
|
get: function get() {
|
|
39
|
-
return _markers.
|
|
39
|
+
return _markers.flattenArrowMarkers;
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
|
-
Object.defineProperty(exports, "
|
|
42
|
+
Object.defineProperty(exports, "flattenSquareMarkers", {
|
|
43
43
|
enumerable: true,
|
|
44
44
|
get: function get() {
|
|
45
|
-
return
|
|
45
|
+
return _markers.flattenSquareMarkers;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
-
Object.defineProperty(exports, "
|
|
48
|
+
Object.defineProperty(exports, "flattenTextMarkers", {
|
|
49
49
|
enumerable: true,
|
|
50
50
|
get: function get() {
|
|
51
|
-
return
|
|
51
|
+
return _markers.flattenTextMarkers;
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
-
Object.defineProperty(exports, "
|
|
54
|
+
Object.defineProperty(exports, "i18n", {
|
|
55
55
|
enumerable: true,
|
|
56
56
|
get: function get() {
|
|
57
|
-
return
|
|
57
|
+
return _i18n["default"];
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
|
-
Object.defineProperty(exports, "
|
|
60
|
+
Object.defineProperty(exports, "parseArrowMarkers", {
|
|
61
61
|
enumerable: true,
|
|
62
62
|
get: function get() {
|
|
63
|
-
return
|
|
63
|
+
return _markers.parseArrowMarkers;
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
-
Object.defineProperty(exports, "
|
|
66
|
+
Object.defineProperty(exports, "parseSquareMarkers", {
|
|
67
67
|
enumerable: true,
|
|
68
68
|
get: function get() {
|
|
69
|
-
return
|
|
69
|
+
return _markers.parseSquareMarkers;
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
|
-
Object.defineProperty(exports, "
|
|
72
|
+
Object.defineProperty(exports, "parseTextMarkers", {
|
|
73
73
|
enumerable: true,
|
|
74
74
|
get: function get() {
|
|
75
|
-
return
|
|
75
|
+
return _markers.parseTextMarkers;
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
78
|
|
package/dist/lib/markers.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.flattenArrowMarkers = flattenArrowMarkers;
|
|
6
7
|
exports.flattenSquareMarkers = flattenSquareMarkers;
|
|
7
8
|
exports.flattenTextMarkers = flattenTextMarkers;
|
|
8
|
-
exports.
|
|
9
|
+
exports.parseArrowMarkers = parseArrowMarkers;
|
|
9
10
|
exports.parseSquareMarkers = parseSquareMarkers;
|
|
10
11
|
exports.parseTextMarkers = parseTextMarkers;
|
|
11
|
-
exports.parseArrowMarkers = parseArrowMarkers;
|
|
12
12
|
|
|
13
13
|
var _util = require("./impl/util");
|
|
14
14
|
|
|
@@ -50,8 +50,8 @@ function flattenSquareMarkers(markers) {
|
|
|
50
50
|
/**
|
|
51
51
|
* Transform a set of text markers defined as a "square -> (symbol, color)" struct into a comma-separated string.
|
|
52
52
|
*
|
|
53
|
-
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
54
|
-
* @returns {string} For example: `'Rzd5,GAe4'`
|
|
53
|
+
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
54
|
+
* @returns {string} For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
57
|
|
|
@@ -69,7 +69,7 @@ function flattenTextMarkers(markers) {
|
|
|
69
69
|
sq = _ref8[0],
|
|
70
70
|
desc = _ref8[1];
|
|
71
71
|
|
|
72
|
-
return desc.color.toUpperCase() + desc.symbol + sq;
|
|
72
|
+
return desc.color.toUpperCase() + (desc.symbol.length === 1 ? desc.symbol : '(' + desc.symbol + ')') + sq;
|
|
73
73
|
}).join(',');
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
@@ -130,17 +130,17 @@ function parseSquareMarkers(markers) {
|
|
|
130
130
|
/**
|
|
131
131
|
* Parse a set of text markers defined as a comma-separated string into a "square -> (symbol, color)" struct.
|
|
132
132
|
*
|
|
133
|
-
* @param {string} markers For example: `'Rzd5,GAe4'`
|
|
134
|
-
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
133
|
+
* @param {string} markers For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
134
|
+
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
135
135
|
*/
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
function parseTextMarkers(markers) {
|
|
139
139
|
return parseMarkers(markers, function (token) {
|
|
140
|
-
return /^([GRY])([A-Za-z0-9])([a-h][1-8])$/.test(token) ? {
|
|
141
|
-
key: RegExp.$
|
|
140
|
+
return /^([GRY])(?:([A-Za-z0-9])|\((plus|times|dot|circle)\))([a-h][1-8])$/.test(token) ? {
|
|
141
|
+
key: RegExp.$4,
|
|
142
142
|
value: {
|
|
143
|
-
symbol: RegExp.$2,
|
|
143
|
+
symbol: RegExp.$2 || RegExp.$3,
|
|
144
144
|
color: RegExp.$1.toLowerCase()
|
|
145
145
|
}
|
|
146
146
|
} : undefined;
|
|
@@ -152,9 +152,10 @@ export default class Page extends React.Component {
|
|
|
152
152
|
if (this.state.interactionMode !== 'editTextMarkers') {
|
|
153
153
|
return undefined;
|
|
154
154
|
}
|
|
155
|
+
let availableSymbols = [ 'plus', 'times', 'dot', 'circle' ].concat([...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789']);
|
|
155
156
|
return (
|
|
156
157
|
<Select variant="standard" value={this.state.textMarkerSymbol} onChange={evt => this.set('textMarkerSymbol', evt.target.value)}>
|
|
157
|
-
{
|
|
158
|
+
{availableSymbols.map(mode => <MenuItem key={mode} value={mode}>{mode}</MenuItem>)}
|
|
158
159
|
</Select>
|
|
159
160
|
);
|
|
160
161
|
}
|
|
Binary file
|
|
@@ -27,11 +27,13 @@ import { SquareMarkerIcon, TextMarkerIcon, ArrowMarkerIcon } from '../src/index'
|
|
|
27
27
|
testApp([ /* eslint-disable react/jsx-key */
|
|
28
28
|
<SquareMarkerIcon size={40} />,
|
|
29
29
|
<SquareMarkerIcon size={45} color="green" />,
|
|
30
|
-
<div style={{ color: 'purple' }}
|
|
30
|
+
<div style={{ color: 'purple' }}><SquareMarkerIcon size={31} /></div>,
|
|
31
31
|
<TextMarkerIcon size={41} symbol="A" />,
|
|
32
32
|
<TextMarkerIcon size={29} symbol="b" color="#0ff" />,
|
|
33
|
-
<div style={{ color: 'red' }}
|
|
33
|
+
<div style={{ color: 'red' }}><TextMarkerIcon size={53} symbol="5" /></div>,
|
|
34
34
|
<ArrowMarkerIcon size={40} />,
|
|
35
35
|
<ArrowMarkerIcon size={24} color="#888" />,
|
|
36
|
-
<div style={{ color: '#f70' }}
|
|
36
|
+
<div style={{ color: '#f70' }}><ArrowMarkerIcon size={48} /></div>,
|
|
37
|
+
<TextMarkerIcon size={47} symbol="dot" color="#00f" />,
|
|
38
|
+
<div style={{ color: 'pink' }}><TextMarkerIcon size={48} symbol="circle" /></div>,
|
|
37
39
|
]); /* eslint-enable react/jsx-key */
|
|
@@ -34,7 +34,7 @@ let textMarkers2 = { g3: { symbol: 'H', color: 'r' }, g5: { symbol: 'M', color:
|
|
|
34
34
|
|
|
35
35
|
let squareMarkers3 = { b5: 'r', e4: 'g', h5: 'y' };
|
|
36
36
|
let arrowMarkers3 = { d1h5: 'g', a5f4: 'r', c7c3: 'y', g7g7: 'g' };
|
|
37
|
-
let textMarkers3 = 'G5c6';
|
|
37
|
+
let textMarkers3 = 'G5c6,R(plus)a1,G(times)b1,R(dot)a2,Y(circle)b2';
|
|
38
38
|
|
|
39
39
|
testApp([ /* eslint-disable react/jsx-key */
|
|
40
40
|
<Chessboard squareMarkers={squareMarkers1} arrowMarkers={arrowMarkers1} textMarkers={textMarkers1} flipped={false} coordinateVisible={true} />,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kokopu-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A React-based library to create and display chessboard components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chess",
|
|
@@ -37,33 +37,33 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@babel/cli": "^7.15.7",
|
|
40
|
-
"@babel/core": "^7.15.
|
|
41
|
-
"@babel/preset-env": "^7.15.
|
|
40
|
+
"@babel/core": "^7.15.8",
|
|
41
|
+
"@babel/preset-env": "^7.15.8",
|
|
42
42
|
"@babel/preset-react": "^7.14.5",
|
|
43
|
-
"@emotion/react": "^11.
|
|
43
|
+
"@emotion/react": "^11.5.0",
|
|
44
44
|
"@emotion/styled": "^11.3.0",
|
|
45
|
-
"@mui/material": "^5.0.
|
|
46
|
-
"babel-loader": "^8.2.
|
|
47
|
-
"babel-plugin-istanbul": "^6.
|
|
45
|
+
"@mui/material": "^5.0.4",
|
|
46
|
+
"babel-loader": "^8.2.3",
|
|
47
|
+
"babel-plugin-istanbul": "^6.1.1",
|
|
48
48
|
"copy-webpack-plugin": "^9.0.1",
|
|
49
49
|
"coveralls": "^3.1.1",
|
|
50
|
-
"css-loader": "^6.
|
|
51
|
-
"eslint": "^
|
|
52
|
-
"eslint-plugin-react": "^7.26.
|
|
53
|
-
"html-webpack-plugin": "^5.
|
|
50
|
+
"css-loader": "^6.4.0",
|
|
51
|
+
"eslint": "^8.0.1",
|
|
52
|
+
"eslint-plugin-react": "^7.26.1",
|
|
53
|
+
"html-webpack-plugin": "^5.4.0",
|
|
54
54
|
"img-diff-js": "^0.5.2",
|
|
55
|
-
"mocha": "^9.1.
|
|
55
|
+
"mocha": "^9.1.3",
|
|
56
56
|
"null-loader": "^4.0.1",
|
|
57
57
|
"nyc": "^15.1.0",
|
|
58
58
|
"prompt": "^1.2.0",
|
|
59
59
|
"react-dom": "^17.0.2",
|
|
60
60
|
"react-styleguidist": "^11.1.7",
|
|
61
|
-
"selenium-webdriver": "^4.0.0
|
|
62
|
-
"ssh2-sftp-client": "^7.0
|
|
61
|
+
"selenium-webdriver": "^4.0.0",
|
|
62
|
+
"ssh2-sftp-client": "^7.1.0",
|
|
63
63
|
"style-loader": "^3.3.0",
|
|
64
64
|
"unit.js": "^2.1.1",
|
|
65
|
-
"webpack": "^5.
|
|
66
|
-
"webpack-cli": "^4.
|
|
65
|
+
"webpack": "^5.59.0",
|
|
66
|
+
"webpack-cli": "^4.9.1"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"lint": "eslint doc_src graphic_test_app src test",
|
|
@@ -47,6 +47,7 @@ module.exports = {
|
|
|
47
47
|
entry: entries,
|
|
48
48
|
output: {
|
|
49
49
|
path: path.resolve(__dirname, '../../build/test_graphic'),
|
|
50
|
+
hashFunction: "xxhash64", // FIXME The default hash function used by Webpack has been removed from OpenSSL.
|
|
50
51
|
},
|
|
51
52
|
plugins: plugins,
|
|
52
53
|
module: {
|
package/src/ArrowMarkerIcon.js
CHANGED
|
@@ -54,7 +54,7 @@ export default class ArrowMarkerIcon extends React.Component {
|
|
|
54
54
|
<ArrowTip id={this.arrowTipId} color={this.props.color} />
|
|
55
55
|
</defs>
|
|
56
56
|
<line className="kokopu-arrow" x1={halfThickness} y1={size / 2} x2={size - halfThickness * 3} y2={size / 2} stroke={this.props.color}
|
|
57
|
-
|
|
57
|
+
strokeWidth={halfThickness * 2} markerEnd={`url(#${this.arrowTipId})`} />
|
|
58
58
|
</svg>
|
|
59
59
|
);
|
|
60
60
|
}
|
package/src/Chessboard.js
CHANGED
|
@@ -29,6 +29,7 @@ import kokopu from 'kokopu';
|
|
|
29
29
|
import colorsets from './impl/colorsets';
|
|
30
30
|
import piecesets from './impl/piecesets';
|
|
31
31
|
import ArrowTip from './impl/ArrowTip';
|
|
32
|
+
import TextSymbol from './impl/TextSymbol';
|
|
32
33
|
import ErrorBox from './ErrorBox';
|
|
33
34
|
import i18n from './i18n';
|
|
34
35
|
import { parseSquareMarkers, parseTextMarkers, parseArrowMarkers } from './markers';
|
|
@@ -272,7 +273,7 @@ export default class Chessboard extends React.Component {
|
|
|
272
273
|
return (
|
|
273
274
|
<line
|
|
274
275
|
className="kokopu-annotation kokopu-arrow kokopu-arrowDraggable kokopu-dragging" x1={xFrom} y1={yFrom} x2={xTo} y2={yTo}
|
|
275
|
-
stroke={colorset[this.props.editedArrowColor]}
|
|
276
|
+
stroke={colorset[this.props.editedArrowColor]} strokeWidth={strokeWidth} markerEnd={`url(#${arrowTipId})`}
|
|
276
277
|
/>
|
|
277
278
|
);
|
|
278
279
|
}
|
|
@@ -347,9 +348,9 @@ export default class Chessboard extends React.Component {
|
|
|
347
348
|
x += squareSize / 2;
|
|
348
349
|
y += squareSize / 2;
|
|
349
350
|
result.push(
|
|
350
|
-
<
|
|
351
|
-
{value.symbol}
|
|
352
|
-
</
|
|
351
|
+
<g key={'txtm-' + sq} className="kokopu-annotation">
|
|
352
|
+
<TextSymbol x={x} y={y} size={squareSize} symbol={value.symbol} color={colorset[value.color]} />
|
|
353
|
+
</g>
|
|
353
354
|
);
|
|
354
355
|
});
|
|
355
356
|
return result;
|
|
@@ -376,7 +377,7 @@ export default class Chessboard extends React.Component {
|
|
|
376
377
|
result.push(
|
|
377
378
|
<line
|
|
378
379
|
key={'arm-' + vect} className="kokopu-annotation kokopu-arrow" x1={xFrom} y1={yFrom} x2={xTo} y2={yTo}
|
|
379
|
-
stroke={colorset[color]}
|
|
380
|
+
stroke={colorset[color]} strokeWidth={strokeWidth} markerEnd={`url(#${arrowTipId})`}
|
|
380
381
|
/>
|
|
381
382
|
);
|
|
382
383
|
});
|
|
@@ -400,7 +401,7 @@ export default class Chessboard extends React.Component {
|
|
|
400
401
|
return (
|
|
401
402
|
<line
|
|
402
403
|
className="kokopu-annotation kokopu-arrow" x1={xFrom} y1={yFrom} x2={x} y2={y} stroke={colorset['highlight']}
|
|
403
|
-
|
|
404
|
+
strokeWidth={squareSize * STROKE_THICKNESS_FACTOR} markerEnd={`url(#${this.getArrowTipId('highlight')})`}
|
|
404
405
|
/>
|
|
405
406
|
);
|
|
406
407
|
}
|
|
@@ -419,14 +420,14 @@ export default class Chessboard extends React.Component {
|
|
|
419
420
|
let x = Math.round(-RANK_COORDINATE_WIDTH_FACTOR * fontSize) / 2;
|
|
420
421
|
let y = (this.props.flipped ? rank + 0.5 : 7.5 - rank) * squareSize;
|
|
421
422
|
let label = RANK_LABELS[rank];
|
|
422
|
-
return <text key={'rank-' + label} className="kokopu-coordinate kokopu-label" x={x} y={y}
|
|
423
|
+
return <text key={'rank-' + label} className="kokopu-coordinate kokopu-label" x={x} y={y} fontSize={fontSize}>{label}</text>;
|
|
423
424
|
}
|
|
424
425
|
|
|
425
426
|
renderFileCoordinate(squareSize, fontSize, file) {
|
|
426
427
|
let x = (this.props.flipped ? 7.5 - file : 0.5 + file) * squareSize;
|
|
427
428
|
let y = 8 * squareSize + Math.round(FILE_COORDINATE_HEIGHT_FACTOR * fontSize) / 2;
|
|
428
429
|
let label = FILE_LABELS[file];
|
|
429
|
-
return <text key={'file-' + label} className="kokopu-coordinate kokopu-label" x={x} y={y}
|
|
430
|
+
return <text key={'file-' + label} className="kokopu-coordinate kokopu-label" x={x} y={y} fontSize={fontSize}>{label}</text>;
|
|
430
431
|
}
|
|
431
432
|
|
|
432
433
|
handleWindowResize() {
|
package/src/TextMarkerIcon.js
CHANGED
|
@@ -23,9 +23,8 @@
|
|
|
23
23
|
import PropTypes from 'prop-types';
|
|
24
24
|
import React from 'react';
|
|
25
25
|
|
|
26
|
-
import './css/label.css';
|
|
27
|
-
|
|
28
26
|
import { MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, sanitizeInteger, isValidSymbol } from './impl/util';
|
|
27
|
+
import TextSymbol from './impl/TextSymbol';
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
/**
|
|
@@ -39,9 +38,7 @@ export default function TextMarkerIcon(props) {
|
|
|
39
38
|
let viewBox = `0 0 ${size} ${size}`;
|
|
40
39
|
return (
|
|
41
40
|
<svg className="kokopu-textMarkerIcon" viewBox={viewBox} width={size} height={size}>
|
|
42
|
-
<
|
|
43
|
-
{props.symbol}
|
|
44
|
-
</text>
|
|
41
|
+
<TextSymbol x={size / 2} y={size / 2} size={size} symbol={props.symbol} color={props.color} />
|
|
45
42
|
</svg>
|
|
46
43
|
);
|
|
47
44
|
}
|
|
@@ -54,7 +51,10 @@ TextMarkerIcon.propTypes = {
|
|
|
54
51
|
size: PropTypes.number.isRequired,
|
|
55
52
|
|
|
56
53
|
/**
|
|
57
|
-
* Symbol to represent on the icon. Must be
|
|
54
|
+
* Symbol to represent on the icon. Must be one of:
|
|
55
|
+
* - any letter from A to Z (either upper-case or lower-case),
|
|
56
|
+
* - any digit from 0 to 9,
|
|
57
|
+
* - any symbol code among `'plus'`, `'times'`, `'dot'`, or `'circle'`.
|
|
58
58
|
*/
|
|
59
59
|
symbol: PropTypes.string.isRequired,
|
|
60
60
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
4
|
+
* Copyright (C) 2021 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
|
+
.kokopu-symbolCircle {
|
|
24
|
+
fill: transparent;
|
|
25
|
+
}
|
package/src/impl/ArrowTip.js
CHANGED
|
@@ -29,7 +29,7 @@ import React from 'react';
|
|
|
29
29
|
*/
|
|
30
30
|
export default function ArrowTip(props) {
|
|
31
31
|
return (
|
|
32
|
-
<marker id={props.id} markerWidth={4} markerHeight={4} refX={2.5} refY={2} orient="auto"
|
|
32
|
+
<marker id={props.id} markerWidth={4} markerHeight={4} refX={2.5} refY={2} orient="auto" fill={props.color}>
|
|
33
33
|
<path d="M 4,2 L 0,4 L 1,2 L 0,0 Z" />
|
|
34
34
|
</marker>
|
|
35
35
|
);
|
|
@@ -45,9 +45,5 @@ ArrowTip.propTypes = {
|
|
|
45
45
|
/**
|
|
46
46
|
* Color to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
|
|
47
47
|
*/
|
|
48
|
-
color: PropTypes.string,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
ArrowTip.defaultProps = {
|
|
52
|
-
color: 'currentcolor',
|
|
48
|
+
color: PropTypes.string.isRequired,
|
|
53
49
|
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* *
|
|
3
|
+
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
4
|
+
* Copyright (C) 2021 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 PropTypes from 'prop-types';
|
|
24
|
+
import React from 'react';
|
|
25
|
+
|
|
26
|
+
import '../css/label.css';
|
|
27
|
+
import '../css/symbol.css';
|
|
28
|
+
|
|
29
|
+
const SHAPE_THICKNESS_FACTOR = 0.1;
|
|
30
|
+
const DOT_RADIUS_FACTOR = 0.15;
|
|
31
|
+
const CIRCLE_RADIUS_FACTOR = 0.425;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Symbol of a text marker.
|
|
36
|
+
*/
|
|
37
|
+
export default function TextSymbol(props) {
|
|
38
|
+
if (props.symbol === 'dot') {
|
|
39
|
+
return <circle cx={props.x} cy={props.y} r={props.size * DOT_RADIUS_FACTOR} fill={props.color} />;
|
|
40
|
+
}
|
|
41
|
+
else if (props.symbol === 'circle') {
|
|
42
|
+
let thickness = props.size * SHAPE_THICKNESS_FACTOR;
|
|
43
|
+
return <circle className="kokopu-symbolCircle" cx={props.x} cy={props.y} r={props.size * CIRCLE_RADIUS_FACTOR} stroke={props.color} strokeWidth={thickness} />;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
let symbol = props.symbol === 'plus' ? '+' : props.symbol === 'times' ? '\u00d7' : props.symbol;
|
|
47
|
+
return <text className="kokopu-label" x={props.x} y={props.y} fill={props.color} fontSize={props.size}>{symbol}</text>;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
TextSymbol.propTypes = {
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* X-coordinate of the center of the symbol.
|
|
55
|
+
*/
|
|
56
|
+
x: PropTypes.number.isRequired,
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Y-coordinate of the center of the symbol.
|
|
60
|
+
*/
|
|
61
|
+
y: PropTypes.number.isRequired,
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Size of the symbol (i.e. size of square in which the symbol is rendered).
|
|
65
|
+
*/
|
|
66
|
+
size: PropTypes.number.isRequired,
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Symbol code.
|
|
70
|
+
*/
|
|
71
|
+
symbol: PropTypes.string.isRequired,
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Color to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
|
|
75
|
+
*/
|
|
76
|
+
color: PropTypes.string.isRequired,
|
|
77
|
+
};
|
package/src/impl/util.js
CHANGED
package/src/markers.js
CHANGED
|
@@ -41,14 +41,14 @@ export function flattenSquareMarkers(markers) {
|
|
|
41
41
|
/**
|
|
42
42
|
* Transform a set of text markers defined as a "square -> (symbol, color)" struct into a comma-separated string.
|
|
43
43
|
*
|
|
44
|
-
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
45
|
-
* @returns {string} For example: `'Rzd5,GAe4'`
|
|
44
|
+
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
45
|
+
* @returns {string} For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
46
46
|
*/
|
|
47
47
|
export function flattenTextMarkers(markers) {
|
|
48
48
|
return Object.entries(markers)
|
|
49
49
|
.filter(([ sq, desc ]) => isValidSquare(sq) && desc && isValidColor(desc.color) && isValidSymbol(desc.symbol))
|
|
50
50
|
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
51
|
-
.map(([ sq, desc ]) => desc.color.toUpperCase() + desc.symbol + sq)
|
|
51
|
+
.map(([ sq, desc ]) => desc.color.toUpperCase() + (desc.symbol.length === 1 ? desc.symbol : '(' + desc.symbol + ')') + sq)
|
|
52
52
|
.join(',');
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -91,12 +91,13 @@ export function parseSquareMarkers(markers) {
|
|
|
91
91
|
/**
|
|
92
92
|
* Parse a set of text markers defined as a comma-separated string into a "square -> (symbol, color)" struct.
|
|
93
93
|
*
|
|
94
|
-
* @param {string} markers For example: `'Rzd5,GAe4'`
|
|
95
|
-
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
94
|
+
* @param {string} markers For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
95
|
+
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
96
96
|
*/
|
|
97
97
|
export function parseTextMarkers(markers) {
|
|
98
98
|
return parseMarkers(markers, token => {
|
|
99
|
-
return /^([GRY])([A-Za-z0-9])([a-h][1-8])$/.test(token) ?
|
|
99
|
+
return /^([GRY])(?:([A-Za-z0-9])|\((plus|times|dot|circle)\))([a-h][1-8])$/.test(token) ?
|
|
100
|
+
{ key: RegExp.$4, value: { symbol: RegExp.$2 || RegExp.$3, color: RegExp.$1.toLowerCase() } } : undefined;
|
|
100
101
|
});
|
|
101
102
|
}
|
|
102
103
|
|
package/test/1_markers.js
CHANGED
|
@@ -65,6 +65,13 @@ describe('Flatten text markers', () => {
|
|
|
65
65
|
h7: { symbol: 'x', color: 'r' },
|
|
66
66
|
d2: { symbol: 'L', color: 'r' },
|
|
67
67
|
})).is('G2a1,YMc5,RLd2,Rxh7,Ywh8'); });
|
|
68
|
+
it('Multi-character symbols', () => { test.value(flattenTextMarkers({
|
|
69
|
+
a1: { symbol: 'A', color: 'y' },
|
|
70
|
+
a7: { symbol: 'plus', color: 'g' },
|
|
71
|
+
b3: { symbol: 'times', color: 'r' },
|
|
72
|
+
g5: { symbol: 'dot', color: 'y' },
|
|
73
|
+
h3: { symbol: 'circle', color: 'g' },
|
|
74
|
+
})).is('YAa1,G(plus)a7,R(times)b3,Y(dot)g5,G(circle)h3'); });
|
|
68
75
|
it('<empty>', () => { test.value(flattenTextMarkers({})).is(''); });
|
|
69
76
|
|
|
70
77
|
it('Wrong square', () => { test.value(flattenTextMarkers({
|
|
@@ -83,6 +90,10 @@ describe('Flatten text markers', () => {
|
|
|
83
90
|
d8: { symbol: '-', color: 'r' },
|
|
84
91
|
c1: { symbol: 'abcd', color: 'r' },
|
|
85
92
|
})).is('G0a2'); });
|
|
93
|
+
it('Wrong multi-character symbol', () => { test.value(flattenTextMarkers({
|
|
94
|
+
a2: { symbol: '0', color: 'g' },
|
|
95
|
+
b5: { symbol: 'whatever', color: 'r' },
|
|
96
|
+
})).is('G0a2'); });
|
|
86
97
|
});
|
|
87
98
|
|
|
88
99
|
|
|
@@ -100,6 +111,13 @@ describe('Parse text markers', () => {
|
|
|
100
111
|
h7: { symbol: 'x', color: 'r' },
|
|
101
112
|
d2: { symbol: 'L', color: 'r' },
|
|
102
113
|
}); });
|
|
114
|
+
it('Multi-character symbols', () => { test.value(parseTextMarkers('YAa1,G(plus)a7, R(times)b3 ,Y(dot)g5,G(circle)h3')).is({
|
|
115
|
+
a1: { symbol: 'A', color: 'y' },
|
|
116
|
+
a7: { symbol: 'plus', color: 'g' },
|
|
117
|
+
b3: { symbol: 'times', color: 'r' },
|
|
118
|
+
g5: { symbol: 'dot', color: 'y' },
|
|
119
|
+
h3: { symbol: 'circle', color: 'g' },
|
|
120
|
+
}); });
|
|
103
121
|
it('<empty>', () => { test.value(parseTextMarkers('')).is({}); });
|
|
104
122
|
it('<blank>', () => { test.value(parseTextMarkers(' ')).is({}); });
|
|
105
123
|
|
|
@@ -107,6 +125,7 @@ describe('Parse text markers', () => {
|
|
|
107
125
|
it('Duplicated square', () => { test.value(parseTextMarkers('Rka3,Gba3')).is({ a3: { symbol: 'b', color: 'g' } }); });
|
|
108
126
|
it('Wrong color', () => { test.value(parseTextMarkers('G3a6,BAg5')).is({ a6: { symbol: '3', color: 'g' } }); });
|
|
109
127
|
it('Wrong symbol', () => { test.value(parseTextMarkers('Rb2,RAg5,G.d3,Yabcde7')).is({ g5: { symbol: 'A', color: 'r' } }); });
|
|
128
|
+
it('Wrong multi-character symbol', () => { test.value(parseTextMarkers('RZb2,Y(whatever)e4')).is({ b2: { symbol: 'Z', color: 'r' } }); });
|
|
110
129
|
it('Wrong format', () => { test.value(parseTextMarkers('Something RHa2 invalid, Yqe4, G g3')).is({ e4: { symbol: 'q', color: 'y' } }); });
|
|
111
130
|
});
|
|
112
131
|
|
|
@@ -36,5 +36,5 @@ describe('Marker icons graphic', function() {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
itChecksScreenshots(browserContext, '01_marker_icons', [ 'default square', 'colorized square', 'wrapped square', 'default text', 'colorized text', 'wrapped text',
|
|
39
|
-
'default arrow', 'colorized arrow', 'wrapped arrow' ]);
|
|
39
|
+
'default arrow', 'colorized arrow', 'wrapped arrow', 'colorized symbol', 'wrapped symbol' ]);
|
|
40
40
|
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|