kokopu-react 1.4.0 → 1.5.1

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.
Files changed (195) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/lib/ArrowMarkerIcon.js +3 -3
  4. package/dist/lib/Chessboard.js +6 -8
  5. package/dist/lib/ErrorBox.js +85 -5
  6. package/dist/lib/Movetext.js +851 -0
  7. package/dist/lib/SquareMarkerIcon.js +1 -1
  8. package/dist/lib/TextMarkerIcon.js +1 -1
  9. package/dist/lib/css/arrow.css +1 -1
  10. package/dist/lib/css/chessboard.css +6 -1
  11. package/dist/lib/css/error_box.css +13 -2
  12. package/dist/lib/css/{label.css → fonts.css} +11 -6
  13. package/dist/lib/css/movetext.css +117 -0
  14. package/dist/lib/css/symbol.css +9 -1
  15. package/dist/lib/fonts/chessalpha.woff +0 -0
  16. package/dist/lib/fonts/chessalpha.woff2 +0 -0
  17. package/dist/lib/i18n.js +17 -2
  18. package/dist/lib/impl/ArrowTip.js +1 -1
  19. package/dist/lib/impl/HtmlSanitizer.js +171 -0
  20. package/dist/lib/impl/TextSymbol.js +2 -4
  21. package/dist/lib/impl/colorsets.js +1 -1
  22. package/dist/lib/impl/piecesets.js +1 -1
  23. package/dist/lib/impl/util.js +1 -1
  24. package/dist/lib/index.js +8 -0
  25. package/doc_src/demo/PageChessboardBase.js +1 -1
  26. package/doc_src/demo/{PageChessboardEdition.js → PageChessboardInteraction.js} +2 -4
  27. package/doc_src/demo/PageChessboardMove.js +1 -1
  28. package/doc_src/demo/PageChessboardSmallScreens.js +1 -1
  29. package/doc_src/demo/PageMovetextBase.js +214 -0
  30. package/doc_src/demo/PageMovetextInteraction.js +159 -0
  31. package/doc_src/demo/demo.css +8 -1
  32. package/doc_src/demo/game-1.pgn +23 -0
  33. package/doc_src/demo/game-2.pgn +22 -0
  34. package/doc_src/demo/game-invalid.pgn +10 -0
  35. package/doc_src/demo/util.js +1 -1
  36. package/doc_src/examples/Movetext.md +15 -0
  37. package/doc_src/home.md +2 -0
  38. package/doc_src/theming/LogoRenderer.js +1 -1
  39. package/doc_src/theming/theming.css +1 -1
  40. package/graphic_test_app/01_marker_icons.js +1 -1
  41. package/graphic_test_app/02_chessboard_simple.js +1 -1
  42. package/graphic_test_app/03_chessboard_flipped.js +1 -1
  43. package/graphic_test_app/04_chessboard_annotations.js +1 -1
  44. package/graphic_test_app/05_chessboard_move.js +1 -1
  45. package/graphic_test_app/06_chessboard_theme.js +1 -1
  46. package/graphic_test_app/07_chessboard_click_squares.js +1 -1
  47. package/graphic_test_app/08_chessboard_move_pieces.js +1 -1
  48. package/graphic_test_app/09_chessboard_edit_arrows.js +1 -1
  49. package/graphic_test_app/10_chessboard_play_moves.js +1 -1
  50. package/graphic_test_app/11_chessboard_play_promotions.js +1 -1
  51. package/graphic_test_app/12_movetext_simple.js +41 -0
  52. package/graphic_test_app/13_movetext_error.js +38 -0
  53. package/graphic_test_app/14_movetext_html.js +40 -0
  54. package/graphic_test_app/15_movetext_options.js +42 -0
  55. package/graphic_test_app/16_movetext_interaction.js +42 -0
  56. package/graphic_test_app/common/dummy.pgn +8 -0
  57. package/graphic_test_app/common/games.pgn +167 -0
  58. package/graphic_test_app/common/heartbeat.txt +1 -0
  59. package/graphic_test_app/common/test_app.css +20 -4
  60. package/graphic_test_app/common/test_app.js +6 -6
  61. package/package.json +26 -25
  62. package/scripts/test_graphic/clean-graphic-output.js +1 -1
  63. package/scripts/test_graphic/docker-compose.yml +1 -1
  64. package/scripts/test_graphic/webpack-config.js +7 -3
  65. package/scripts/test_headless.webpack-config.js +2 -2
  66. package/src/ArrowMarkerIcon.js +1 -1
  67. package/src/Chessboard.js +6 -7
  68. package/src/ErrorBox.js +80 -1
  69. package/src/Movetext.js +627 -0
  70. package/src/SquareMarkerIcon.js +1 -1
  71. package/src/TextMarkerIcon.js +1 -1
  72. package/src/css/arrow.css +1 -1
  73. package/src/css/chessboard.css +6 -1
  74. package/src/css/error_box.css +13 -2
  75. package/src/css/{label.css → fonts.css} +11 -6
  76. package/src/css/movetext.css +117 -0
  77. package/src/css/symbol.css +9 -1
  78. package/src/fonts/chessalpha.woff +0 -0
  79. package/src/fonts/chessalpha.woff2 +0 -0
  80. package/src/i18n.js +12 -1
  81. package/src/impl/ArrowTip.js +1 -1
  82. package/src/impl/HtmlSanitizer.js +120 -0
  83. package/src/impl/TextSymbol.js +2 -3
  84. package/src/impl/colorsets.js +1 -1
  85. package/src/impl/piecesets.js +1 -1
  86. package/src/impl/util.js +1 -1
  87. package/src/index.js +2 -1
  88. package/src/markers.js +1 -1
  89. package/test/1_markers.js +1 -1
  90. package/test/2_chessboard_util.js +1 -1
  91. package/test/3_marker_icons_graphic.js +1 -1
  92. package/test/4_chessboard_graphic.js +1 -1
  93. package/test/5_chessboard_interaction.js +1 -1
  94. package/test/6_chessboard_play_moves.js +1 -1
  95. package/test/7_movetext_graphic.js +43 -0
  96. package/test/8_movetext_interaction.js +103 -0
  97. package/test/common/graphic.js +2 -2
  98. package/test/references/01_marker_icons/0.png +0 -0
  99. package/test/references/01_marker_icons/1.png +0 -0
  100. package/test/references/01_marker_icons/10.png +0 -0
  101. package/test/references/01_marker_icons/2.png +0 -0
  102. package/test/references/01_marker_icons/3.png +0 -0
  103. package/test/references/01_marker_icons/4.png +0 -0
  104. package/test/references/01_marker_icons/5.png +0 -0
  105. package/test/references/01_marker_icons/6.png +0 -0
  106. package/test/references/01_marker_icons/7.png +0 -0
  107. package/test/references/01_marker_icons/8.png +0 -0
  108. package/test/references/01_marker_icons/9.png +0 -0
  109. package/test/references/02_chessboard_simple/0.png +0 -0
  110. package/test/references/02_chessboard_simple/1.png +0 -0
  111. package/test/references/02_chessboard_simple/2.png +0 -0
  112. package/test/references/02_chessboard_simple/3.png +0 -0
  113. package/test/references/02_chessboard_simple/4.png +0 -0
  114. package/test/references/02_chessboard_simple/5.png +0 -0
  115. package/test/references/03_chessboard_flipped/0.png +0 -0
  116. package/test/references/03_chessboard_flipped/1.png +0 -0
  117. package/test/references/03_chessboard_flipped/2.png +0 -0
  118. package/test/references/03_chessboard_flipped/3.png +0 -0
  119. package/test/references/03_chessboard_flipped/4.png +0 -0
  120. package/test/references/04_chessboard_annotations/0.png +0 -0
  121. package/test/references/04_chessboard_annotations/1.png +0 -0
  122. package/test/references/04_chessboard_annotations/2.png +0 -0
  123. package/test/references/04_chessboard_annotations/3.png +0 -0
  124. package/test/references/04_chessboard_annotations/4.png +0 -0
  125. package/test/references/04_chessboard_annotations/5.png +0 -0
  126. package/test/references/05_chessboard_move/0.png +0 -0
  127. package/test/references/05_chessboard_move/1.png +0 -0
  128. package/test/references/05_chessboard_move/2.png +0 -0
  129. package/test/references/05_chessboard_move/3.png +0 -0
  130. package/test/references/05_chessboard_move/4.png +0 -0
  131. package/test/references/05_chessboard_move/5.png +0 -0
  132. package/test/references/05_chessboard_move/6.png +0 -0
  133. package/test/references/05_chessboard_move/7.png +0 -0
  134. package/test/references/05_chessboard_move/8.png +0 -0
  135. package/test/references/06_chessboard_theme/0.png +0 -0
  136. package/test/references/06_chessboard_theme/1.png +0 -0
  137. package/test/references/06_chessboard_theme/2.png +0 -0
  138. package/test/references/06_chessboard_theme/3.png +0 -0
  139. package/test/references/06_chessboard_theme/4.png +0 -0
  140. package/test/references/06_chessboard_theme/5.png +0 -0
  141. package/test/references/06_chessboard_theme/6.png +0 -0
  142. package/test/references/06_chessboard_theme/7.png +0 -0
  143. package/test/references/06_chessboard_theme/8.png +0 -0
  144. package/test/references/08_chessboard_move_pieces/after_move.png +0 -0
  145. package/test/references/08_chessboard_move_pieces/empty_square.png +0 -0
  146. package/test/references/08_chessboard_move_pieces/null_vector.png +0 -0
  147. package/test/references/08_chessboard_move_pieces/out_of_board.png +0 -0
  148. package/test/references/08_chessboard_move_pieces/over_arrow_marker.png +0 -0
  149. package/test/references/08_chessboard_move_pieces/over_empty.png +0 -0
  150. package/test/references/08_chessboard_move_pieces/over_non_empty_1.png +0 -0
  151. package/test/references/08_chessboard_move_pieces/over_non_empty_2.png +0 -0
  152. package/test/references/08_chessboard_move_pieces/over_square_marker.png +0 -0
  153. package/test/references/08_chessboard_move_pieces/over_text_marker.png +0 -0
  154. package/test/references/09_chessboard_edit_arrows/base_1.png +0 -0
  155. package/test/references/09_chessboard_edit_arrows/base_2.png +0 -0
  156. package/test/references/09_chessboard_edit_arrows/edit_color_not_set.png +0 -0
  157. package/test/references/09_chessboard_edit_arrows/null_vector.png +0 -0
  158. package/test/references/09_chessboard_edit_arrows/out_of_board.png +0 -0
  159. package/test/references/09_chessboard_edit_arrows/over_arrow_marker.png +0 -0
  160. package/test/references/09_chessboard_edit_arrows/over_square_marker.png +0 -0
  161. package/test/references/10_chessboard_play_moves/castling_move.png +0 -0
  162. package/test/references/10_chessboard_play_moves/chess960_ambiguous_king_move.png +0 -0
  163. package/test/references/10_chessboard_play_moves/chess960_castling_move_1.png +0 -0
  164. package/test/references/10_chessboard_play_moves/chess960_castling_move_2.png +0 -0
  165. package/test/references/10_chessboard_play_moves/chess960_non_kxr_castling.png +0 -0
  166. package/test/references/10_chessboard_play_moves/illegal_move.png +0 -0
  167. package/test/references/10_chessboard_play_moves/illegal_position.png +0 -0
  168. package/test/references/10_chessboard_play_moves/null_vector.png +0 -0
  169. package/test/references/10_chessboard_play_moves/out_of_board.png +0 -0
  170. package/test/references/10_chessboard_play_moves/regular_move_1.png +0 -0
  171. package/test/references/10_chessboard_play_moves/regular_move_2.png +0 -0
  172. package/test/references/10_chessboard_play_moves/wrong_color.png +0 -0
  173. package/test/references/11_chessboard_play_promotions/antichess_promotion.png +0 -0
  174. package/test/references/11_chessboard_play_promotions/cancel_promotion.png +0 -0
  175. package/test/references/11_chessboard_play_promotions/regular_promotion_1.png +0 -0
  176. package/test/references/11_chessboard_play_promotions/regular_promotion_2.png +0 -0
  177. package/test/references/12_movetext_simple/0.png +0 -0
  178. package/test/references/12_movetext_simple/1.png +0 -0
  179. package/test/references/12_movetext_simple/2.png +0 -0
  180. package/test/references/12_movetext_simple/3.png +0 -0
  181. package/test/references/13_movetext_error/0.png +0 -0
  182. package/test/references/13_movetext_error/1.png +0 -0
  183. package/test/references/13_movetext_error/2.png +0 -0
  184. package/test/references/13_movetext_error/3.png +0 -0
  185. package/test/references/14_movetext_html/0.png +0 -0
  186. package/test/references/14_movetext_html/1.png +0 -0
  187. package/test/references/14_movetext_html/2.png +0 -0
  188. package/test/references/15_movetext_options/0.png +0 -0
  189. package/test/references/15_movetext_options/1.png +0 -0
  190. package/test/references/15_movetext_options/2.png +0 -0
  191. package/test/references/15_movetext_options/3.png +0 -0
  192. package/test/references/16_movetext_interaction/0.png +0 -0
  193. package/test/references/16_movetext_interaction/1.png +0 -0
  194. package/test/references/16_movetext_interaction/2.png +0 -0
  195. package/graphic_test_app/common/healthcheck.txt +0 -1
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -36,6 +36,17 @@
36
36
  font-style: italic;
37
37
  }
38
38
 
39
- .kokopu-errorMessage {
39
+ .kokopu-errorMessage,
40
+ .kokopu-errorExcerpt {
40
41
  margin-top: 0.4em;
41
42
  }
43
+
44
+ .kokopu-errorExcerpt {
45
+ white-space: pre-wrap;
46
+ font-family: monospace;
47
+ line-height: 1.5em;
48
+ color: #400;
49
+ background-color: #ffd;
50
+ border: solid 1px #aa0;
51
+ padding: 0.75em 1em 0.15em;
52
+ }
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -20,10 +20,15 @@
20
20
  ******************************************************************************/
21
21
 
22
22
 
23
- .kokopu-label {
23
+ @font-face {
24
+ font-family: 'Chess Alpha';
25
+ src:
26
+ url('../fonts/chessalpha.woff2') format('woff2'),
27
+ url('../fonts/chessalpha.woff') format('woff');
28
+ font-weight: normal;
24
29
  font-style: normal;
25
- font-family: sans-serif;
26
- text-anchor: middle;
27
- dominant-baseline: central;
28
- letter-spacing: 0px;
30
+ }
31
+
32
+ .kokopu-font-alpha {
33
+ font-family: 'Chess Alpha', sans-serif;
29
34
  }
@@ -0,0 +1,117 @@
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
+ .kokopu-colorTag {
24
+ width : 1.2em;
25
+ height: 1.2em;
26
+ vertical-align: middle;
27
+ display: inline-block;
28
+ border: 1px solid black;
29
+ margin-right: 0.25em;
30
+ }
31
+
32
+ .kokopu-headerGroup-whitePlayer .kokopu-colorTag {
33
+ background-color: white;
34
+ }
35
+
36
+ .kokopu-headerGroup-blackPlayer .kokopu-colorTag {
37
+ background-color: black;
38
+ }
39
+
40
+ .kokopu-headerGroup-titleRating:before,
41
+ .kokopu-header-round:before {
42
+ content: "\a0("; /* \a0 == &nbsp; */
43
+ }
44
+
45
+ .kokopu-headerGroup-titleRating:after,
46
+ .kokopu-header-round:after {
47
+ content: ")";
48
+ }
49
+
50
+ .kokopu-header-round,
51
+ .kokopu-header-annotator {
52
+ font-style: italic;
53
+ }
54
+
55
+ * + .kokopu-move:before,
56
+ * + .kokopu-gameResult:before,
57
+ * + span.kokopu-comment:before {
58
+ content: " ";
59
+ }
60
+
61
+ span.kokopu-variation:before {
62
+ content: " (";
63
+ }
64
+
65
+ span.kokopu-variation:after {
66
+ content: ")";
67
+ }
68
+
69
+ * + .kokopu-nag:before {
70
+ content: "\a0"; /* \a0 == &nbsp; */
71
+ }
72
+
73
+ div.kokopu-subVariation {
74
+ margin-left: 1.5em;
75
+ }
76
+
77
+ .kokopu-move,
78
+ .kokopu-gameResult {
79
+ font-weight: bold;
80
+ }
81
+
82
+ .kokopu-subVariation .kokopu-move {
83
+ font-weight: inherit;
84
+ }
85
+
86
+ .kokopu-diagram {
87
+ text-align: center;
88
+ line-height: 0px;
89
+ }
90
+
91
+ .kokopu-moveContent {
92
+ display: inline-block;
93
+ padding-left: 1px;
94
+ padding-right: 1px;
95
+ }
96
+
97
+ .kokopu-selectedMove .kokopu-moveContent {
98
+ background-color: currentcolor;
99
+ }
100
+
101
+ .kokopu-selectedMove .kokopu-moveContent > * {
102
+ filter: invert(1);
103
+ }
104
+
105
+ .kokopu-clickableMove .kokopu-moveContent:hover {
106
+ text-decoration: underline;
107
+ cursor: pointer;
108
+ }
109
+
110
+ .kokopu-focusFieldContainer {
111
+ position: fixed;
112
+ bottom: 0px;
113
+ right: 0px;
114
+ width: 0px;
115
+ height: 0px;
116
+ overflow: hidden;
117
+ }
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -23,3 +23,11 @@
23
23
  .kokopu-symbolCircle {
24
24
  fill: transparent;
25
25
  }
26
+
27
+ .kokopu-symbolText {
28
+ font-style: normal;
29
+ font-family: sans-serif;
30
+ text-anchor: middle;
31
+ dominant-baseline: central;
32
+ letter-spacing: 0px;
33
+ }
Binary file
Binary file
package/src/i18n.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -21,10 +21,21 @@
21
21
 
22
22
 
23
23
  const i18n = {
24
+
25
+ // Error box
26
+ LINE: 'line {0}',
27
+
28
+ // Chessboard
24
29
  INVALID_FEN_ERROR_TITLE: 'Invalid FEN string.',
25
30
  INVALID_NOTATION_ERROR_TITLE: 'Invalid move notation.',
26
31
  INVALID_POSITION_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "position" attribute.',
27
32
  INVALID_MOVE_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "move" attribute.',
33
+
34
+ // Movetext
35
+ PIECE_SYMBOLS: { 'K':'K', 'Q':'Q', 'R':'R', 'B':'B', 'N':'N', 'P':'P' },
36
+ ANNOTATED_BY: 'Annotated by {0}',
37
+ INVALID_PGN_ERROR_TITLE: 'Invalid PGN string.',
38
+ INVALID_GAME_ATTRIBUTE_ERROR_MESSAGE: 'Invalid "game" attribute.',
28
39
  };
29
40
 
30
41
  export default i18n;
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -0,0 +1,120 @@
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 * as htmlparser2 from 'htmlparser2';
25
+
26
+
27
+ /**
28
+ * HTML sanitizer: parse HTML string, keeping only the allowed HTML nodes, and the corresponding React object.
29
+ */
30
+ export default class HtmlSanitizer {
31
+
32
+ constructor({ allowedTags, allowedAttributes }) {
33
+ this._allowedTags = allowedTags ? new Set(allowedTags) : new Set();
34
+ this._allowedAttributes = allowedAttributes ? new Map(Object.entries(allowedAttributes).map(([k, v]) => [k, new Set(v)])) : new Map();
35
+ this._keyCounter = 0;
36
+ }
37
+
38
+ /**
39
+ * @param {string} text HTML string to be parsed.
40
+ * @returns {*} React object corresponding to the given HTML string. Can also be a fragment, or just a simple string if the given HTML string
41
+ * does not contain any HTML tag.
42
+ */
43
+ parse(text) {
44
+ let dom = htmlparser2.parseDocument(text);
45
+
46
+ // Ensure that the returned object is a non-empty node type.
47
+ if (dom.type !== 'root') {
48
+ return undefined;
49
+ }
50
+
51
+ // Process the children of the root node.
52
+ let result = [];
53
+ dom.children.forEach(child => {
54
+ let childElement = this._processNode(child);
55
+ if (childElement) {
56
+ result.push(childElement);
57
+ }
58
+ });
59
+
60
+ // Return the result.
61
+ if (result.length === 0) {
62
+ return undefined;
63
+ }
64
+ else if (result.length === 1) {
65
+ return result[0];
66
+ }
67
+ else {
68
+ return <React.Fragment key={this._allocateKey()}>{result}</React.Fragment>;
69
+ }
70
+ }
71
+
72
+ _processNode(node) {
73
+ if (node.type === 'text') {
74
+ return node.data;
75
+ }
76
+ else if (node.type === 'tag') {
77
+ let children = node.children.map(child => this._processNode(child));
78
+ if (this._allowedTags.has(node.name)) {
79
+ let attributes = this._filterAttributes(node.name, node.attribs);
80
+ attributes['key'] = this._allocateKey();
81
+ return React.createElement(node.name, attributes, children);
82
+ }
83
+ else {
84
+ return <React.Fragment key={this._allocateKey()}>{children}</React.Fragment>;
85
+ }
86
+ }
87
+ else {
88
+ return undefined;
89
+ }
90
+ }
91
+
92
+ _filterAttributes(nodeName, attributes) {
93
+ let result = {};
94
+ for (let [attribute, value] of Object.entries(attributes)) {
95
+ if (this._isAttributeAllowed(nodeName, attribute)) {
96
+ result[attribute === 'class' ? 'className' : attribute] = value;
97
+ }
98
+ }
99
+ return result;
100
+ }
101
+
102
+ _isAttributeAllowed(nodeName, attribute) {
103
+ if (attribute === 'key' && attribute === 'ref' && attribute === 'className') { // Those attributes are always forbidden.
104
+ return false;
105
+ }
106
+ let allowedAttributesForCurrent = this._allowedAttributes.get(nodeName);
107
+ if (allowedAttributesForCurrent && allowedAttributesForCurrent.has(attribute)) {
108
+ return true;
109
+ }
110
+ let allowedAttributesForAll = this._allowedAttributes.get('*');
111
+ if (allowedAttributesForAll && allowedAttributesForAll.has(attribute)) {
112
+ return true;
113
+ }
114
+ return false;
115
+ }
116
+
117
+ _allocateKey() {
118
+ return 'auto-' + (this._keyCounter++);
119
+ }
120
+ }
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -23,7 +23,6 @@
23
23
  import PropTypes from 'prop-types';
24
24
  import React from 'react';
25
25
 
26
- import '../css/label.css';
27
26
  import '../css/symbol.css';
28
27
 
29
28
  const SHAPE_THICKNESS_FACTOR = 0.1;
@@ -44,7 +43,7 @@ export default function TextSymbol(props) {
44
43
  }
45
44
  else {
46
45
  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>;
46
+ return <text className="kokopu-symbolText" x={props.x} y={props.y} fill={props.color} fontSize={props.size}>{symbol}</text>;
48
47
  }
49
48
  }
50
49
 
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
package/src/impl/util.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
package/src/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -24,6 +24,7 @@ export { flattenSquareMarkers, parseSquareMarkers, flattenTextMarkers, parseText
24
24
  export { default as i18n } from './i18n';
25
25
  export { default as Chessboard } from './Chessboard';
26
26
  export { default as ErrorBox } from './ErrorBox';
27
+ export { default as Movetext } from './Movetext';
27
28
  export { default as SquareMarkerIcon } from './SquareMarkerIcon';
28
29
  export { default as TextMarkerIcon } from './TextMarkerIcon';
29
30
  export { default as ArrowMarkerIcon } from './ArrowMarkerIcon';
package/src/markers.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
package/test/1_markers.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -0,0 +1,43 @@
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
+ const { openBrowser, closeBrowser, itChecksScreenshots } = require('./common/graphic');
24
+
25
+
26
+ describe('Movetext graphic', function() {
27
+
28
+ const browserContext = {};
29
+
30
+ before(async function() {
31
+ await openBrowser(this, browserContext);
32
+ });
33
+
34
+ after(async function() {
35
+ await closeBrowser(browserContext);
36
+ });
37
+
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' ]);
40
+ itChecksScreenshots(browserContext, '14_movetext_html', [ 'html-in-headers', 'html-in-comments', 'filtered-tags-and-attributes' ]);
41
+ itChecksScreenshots(browserContext, '15_movetext_options', [ 'localized-piece-symbols', 'custom-piece-symbols', 'figurine-piece-symbols-and-diagram-options',
42
+ 'hidden-diagrams' ]);
43
+ });
@@ -0,0 +1,103 @@
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
+ const { openBrowser, closeBrowser, itCustom, setSandbox, compareSandbox, takeScreenshot, compareScreenshot } = require('./common/graphic');
24
+ const { By, Key } = require('selenium-webdriver');
25
+
26
+
27
+ describe('Movetext interaction', function() {
28
+
29
+ const browserContext = {};
30
+
31
+ before(async function() {
32
+ await openBrowser(this, browserContext);
33
+ });
34
+
35
+ after(async function() {
36
+ await closeBrowser(browserContext);
37
+ });
38
+
39
+ function itCheckClickMove(itemIndex, label, targets) {
40
+ itCustom(browserContext, '16_movetext_interaction', itemIndex, label, async function(element) {
41
+ let actions = browserContext.driver.actions({ async: true });
42
+ await setSandbox(browserContext, '');
43
+ for (let i = 0; i < targets.length; ++i) {
44
+ let target = targets[i];
45
+ let moveElement = await element.findElement(By.xpath(`.//span[text()='${target.searchedText}']`));
46
+ await actions.move({ origin: moveElement }).click().perform();
47
+ if (i === 0) {
48
+ await takeScreenshot(browserContext, itemIndex, element);
49
+ await compareScreenshot(browserContext, itemIndex);
50
+ }
51
+ await compareSandbox(browserContext, target.expectedText);
52
+ }
53
+ });
54
+ }
55
+
56
+ function tpl(nodeId, evtOrigin) {
57
+ return `move selected: ${nodeId}\norigin: ${evtOrigin}`;
58
+ }
59
+
60
+ itCheckClickMove(0, 'click on disabled', [
61
+ { searchedText: 'Nf6', expectedText: '' },
62
+ { searchedText: 'Qc2', expectedText: '' },
63
+ ]);
64
+
65
+ itCheckClickMove(1, 'click on unselected', [
66
+ { searchedText: 'cxd5', expectedText: tpl('5w', 'click') },
67
+ ]);
68
+
69
+ itCheckClickMove(2, 'click on with variations 1', [
70
+ { searchedText: 'Bb5', expectedText: tpl(undefined, 'click') },
71
+ { searchedText: 'Nc6', expectedText: tpl('1b-v0-2b', 'click') },
72
+ ]);
73
+
74
+ function itCheckKeyboardActions(itemIndex, label, expectedOnGoFirst, expectedOnGoPrevious, expectedOnGoNext, expectedOnGoLast) {
75
+ itCustom(browserContext, '16_movetext_interaction', itemIndex, label, async function(element) {
76
+ let focusFieldElement = await element.findElement(By.className('kokopu-focusField'));
77
+
78
+ await setSandbox(browserContext, '');
79
+ await focusFieldElement.sendKeys(Key.HOME);
80
+ await compareSandbox(browserContext, expectedOnGoFirst);
81
+
82
+ await setSandbox(browserContext, '');
83
+ await focusFieldElement.sendKeys(Key.ARROW_LEFT);
84
+ await compareSandbox(browserContext, expectedOnGoPrevious);
85
+
86
+ await setSandbox(browserContext, '');
87
+ await focusFieldElement.sendKeys(Key.ARROW_RIGHT);
88
+ await compareSandbox(browserContext, expectedOnGoNext);
89
+
90
+ await setSandbox(browserContext, '');
91
+ await focusFieldElement.sendKeys(Key.END);
92
+ await compareSandbox(browserContext, expectedOnGoLast);
93
+ });
94
+ }
95
+
96
+ itCheckKeyboardActions(1, 'key on unselected', '', '', '', '');
97
+ itCheckKeyboardActions(2, 'key on with variations 1', tpl('start', 'key-first'), tpl('1b-v0-2b', 'key-previous'), tpl('1b-v0-3w-v0-3b', 'key-next'), tpl('1b-v0-3w-v0-4w', 'key-last'));
98
+ itCheckKeyboardActions(3, 'key on with variations 2', tpl('start', 'key-first'), tpl('1b-v0-2w', 'key-previous'), tpl('1b-v0-3w', 'key-next'), tpl('1b-v0-3w', 'key-last'));
99
+ itCheckKeyboardActions(4, 'key on start selected', '', '', tpl('1w', 'key-next'), tpl('6b', 'key-last'));
100
+ itCheckKeyboardActions(5, 'key on first selected', tpl('start', 'key-first'), tpl('start', 'key-previous'), tpl('1b', 'key-next'), tpl('6b', 'key-last'));
101
+ itCheckKeyboardActions(6, 'key on last selected', tpl('start', 'key-first'), tpl('6w', 'key-previous'), '', '');
102
+ itCheckKeyboardActions(7, 'key on invalid selection', '', '', '', '');
103
+ });