@johnmorrisdotca/dougu-sports 0.0.1 → 0.2.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.
Files changed (338) hide show
  1. package/CHANGELOG.md +61 -1
  2. package/LICENSES/README.md +4 -3
  3. package/NOTICE.md +54 -14
  4. package/README.md +251 -80
  5. package/dist/emblems/award/badge.d.ts +2 -0
  6. package/dist/emblems/award/badge.js +14 -0
  7. package/dist/emblems/award/crown.d.ts +2 -0
  8. package/dist/emblems/award/crown.js +15 -0
  9. package/dist/emblems/award/medal.d.ts +1 -1
  10. package/dist/emblems/award/medal.js +10 -15
  11. package/dist/emblems/award/shield.d.ts +2 -0
  12. package/dist/emblems/award/shield.js +11 -0
  13. package/dist/emblems/award/star.d.ts +2 -0
  14. package/dist/emblems/award/star.js +11 -0
  15. package/dist/emblems/ball/ball.afl.d.ts +1 -0
  16. package/dist/emblems/ball/ball.afl.js +24 -0
  17. package/dist/emblems/ball/ball.baseball.d.ts +1 -0
  18. package/dist/emblems/ball/ball.baseball.js +14 -0
  19. package/dist/emblems/ball/ball.basketball.d.ts +7 -0
  20. package/dist/emblems/ball/ball.basketball.js +32 -0
  21. package/dist/emblems/ball/ball.basketball3x3.d.ts +1 -0
  22. package/dist/emblems/ball/ball.basketball3x3.js +10 -0
  23. package/dist/emblems/ball/ball.basketball6.d.ts +1 -0
  24. package/dist/emblems/ball/ball.basketball6.js +10 -0
  25. package/dist/emblems/ball/ball.core.d.ts +111 -0
  26. package/dist/emblems/ball/ball.core.js +79 -0
  27. package/dist/emblems/ball/ball.cricket.d.ts +5 -0
  28. package/dist/emblems/ball/ball.cricket.js +31 -0
  29. package/dist/emblems/ball/ball.curlingstone.d.ts +3 -0
  30. package/dist/emblems/ball/ball.curlingstone.js +46 -0
  31. package/dist/emblems/ball/ball.discus.d.ts +1 -0
  32. package/dist/emblems/ball/ball.discus.js +24 -0
  33. package/dist/emblems/ball/ball.engine.d.ts +114 -0
  34. package/dist/emblems/ball/ball.engine.js +342 -0
  35. package/dist/emblems/ball/ball.family.dotted.d.ts +27 -0
  36. package/dist/emblems/ball/ball.family.dotted.js +20 -0
  37. package/dist/emblems/ball/ball.family.panelled.d.ts +7 -0
  38. package/dist/emblems/ball/ball.family.panelled.js +60 -0
  39. package/dist/emblems/ball/ball.family.prolate.d.ts +16 -0
  40. package/dist/emblems/ball/ball.family.prolate.js +29 -0
  41. package/dist/emblems/ball/ball.family.seamed.d.ts +31 -0
  42. package/dist/emblems/ball/ball.family.seamed.js +26 -0
  43. package/dist/emblems/ball/ball.fieldhockey.d.ts +1 -0
  44. package/dist/emblems/ball/ball.fieldhockey.js +15 -0
  45. package/dist/emblems/ball/ball.football.d.ts +3 -0
  46. package/dist/emblems/ball/ball.football.js +51 -0
  47. package/dist/emblems/ball/ball.gaelic.d.ts +2 -0
  48. package/dist/emblems/ball/ball.gaelic.js +30 -0
  49. package/dist/emblems/ball/ball.golf.d.ts +1 -0
  50. package/dist/emblems/ball/ball.golf.js +15 -0
  51. package/dist/emblems/ball/ball.hammer.d.ts +1 -0
  52. package/dist/emblems/ball/ball.hammer.js +31 -0
  53. package/dist/emblems/ball/ball.handball.d.ts +1 -0
  54. package/dist/emblems/ball/ball.handball.js +25 -0
  55. package/dist/emblems/ball/ball.index.d.ts +48 -0
  56. package/dist/emblems/ball/ball.index.js +103 -0
  57. package/dist/emblems/ball/ball.math.d.ts +38 -0
  58. package/dist/emblems/ball/ball.math.js +105 -0
  59. package/dist/emblems/ball/ball.object.d.ts +38 -0
  60. package/dist/emblems/ball/ball.object.js +20 -0
  61. package/dist/emblems/ball/ball.padel.d.ts +1 -0
  62. package/dist/emblems/ball/ball.padel.js +13 -0
  63. package/dist/emblems/ball/ball.pickleball.d.ts +2 -0
  64. package/dist/emblems/ball/ball.pickleball.js +26 -0
  65. package/dist/emblems/ball/ball.polyhedra.d.ts +15 -0
  66. package/dist/emblems/ball/ball.polyhedra.js +63 -0
  67. package/dist/emblems/ball/ball.puck.d.ts +3 -0
  68. package/dist/emblems/ball/ball.puck.js +22 -0
  69. package/dist/emblems/ball/ball.roundnet.d.ts +1 -0
  70. package/dist/emblems/ball/ball.roundnet.js +15 -0
  71. package/dist/emblems/ball/ball.rugby.d.ts +1 -0
  72. package/dist/emblems/ball/ball.rugby.js +35 -0
  73. package/dist/emblems/ball/ball.sepaktakraw.d.ts +1 -0
  74. package/dist/emblems/ball/ball.sepaktakraw.js +48 -0
  75. package/dist/emblems/ball/ball.shuttlecock.d.ts +6 -0
  76. package/dist/emblems/ball/ball.shuttlecock.js +93 -0
  77. package/dist/emblems/ball/ball.sliotar.d.ts +1 -0
  78. package/dist/emblems/ball/ball.sliotar.js +14 -0
  79. package/dist/emblems/ball/ball.smooth.d.ts +4 -0
  80. package/dist/emblems/ball/ball.smooth.js +51 -0
  81. package/dist/emblems/ball/ball.soccer.d.ts +2 -0
  82. package/dist/emblems/ball/ball.soccer.js +54 -0
  83. package/dist/emblems/ball/ball.softball.d.ts +1 -0
  84. package/dist/emblems/ball/ball.softball.js +14 -0
  85. package/dist/emblems/ball/ball.squash.d.ts +7 -0
  86. package/dist/emblems/ball/ball.squash.js +27 -0
  87. package/dist/emblems/ball/ball.stack.d.ts +48 -0
  88. package/dist/emblems/ball/ball.stack.js +127 -0
  89. package/dist/emblems/ball/ball.stitch.d.ts +10 -0
  90. package/dist/emblems/ball/ball.stitch.js +59 -0
  91. package/dist/emblems/ball/ball.tennis.d.ts +1 -0
  92. package/dist/emblems/ball/ball.tennis.js +13 -0
  93. package/dist/emblems/ball/ball.teqball.d.ts +1 -0
  94. package/dist/emblems/ball/ball.teqball.js +27 -0
  95. package/dist/emblems/ball/ball.volleyball.d.ts +3 -0
  96. package/dist/emblems/ball/ball.volleyball.js +56 -0
  97. package/dist/emblems/ball/ball.waterpolo.d.ts +1 -0
  98. package/dist/emblems/ball/ball.waterpolo.js +31 -0
  99. package/dist/emblems/crest/diamond.d.ts +2 -0
  100. package/dist/emblems/crest/diamond.js +18 -0
  101. package/dist/emblems/crest/pennant.d.ts +2 -0
  102. package/dist/emblems/crest/pennant.js +18 -0
  103. package/dist/emblems/crest/roundel.d.ts +2 -0
  104. package/dist/emblems/crest/roundel.js +18 -0
  105. package/dist/emblems/crest/shield.d.ts +2 -0
  106. package/dist/emblems/crest/shield.js +17 -0
  107. package/dist/emblems/emblem.api.d.ts +77 -9
  108. package/dist/emblems/emblem.api.js +56 -10
  109. package/dist/emblems/emblem.compose.d.ts +31 -0
  110. package/dist/emblems/emblem.compose.js +91 -0
  111. package/dist/emblems/emblem.core.d.ts +89 -7
  112. package/dist/emblems/emblem.core.js +85 -11
  113. package/dist/emblems/emblem.descriptions.d.ts +7 -0
  114. package/dist/emblems/emblem.descriptions.js +60 -0
  115. package/dist/emblems/emblem.display.d.ts +75 -0
  116. package/dist/emblems/emblem.display.js +214 -0
  117. package/dist/emblems/emblem.engrave.d.ts +50 -0
  118. package/dist/emblems/emblem.engrave.js +145 -0
  119. package/dist/emblems/emblem.equipment.d.ts +24 -0
  120. package/dist/emblems/emblem.equipment.js +57 -0
  121. package/dist/emblems/emblem.flip.d.ts +10 -0
  122. package/dist/emblems/emblem.flip.js +45 -0
  123. package/dist/emblems/emblem.ids.d.ts +44 -30
  124. package/dist/emblems/emblem.ids.js +51 -17
  125. package/dist/emblems/emblem.lathe.d.ts +62 -0
  126. package/dist/emblems/emblem.lathe.js +426 -0
  127. package/dist/emblems/emblem.medal.d.ts +6 -0
  128. package/dist/emblems/emblem.medal.js +38 -0
  129. package/dist/emblems/emblem.pennant.d.ts +3 -0
  130. package/dist/emblems/emblem.pennant.js +79 -0
  131. package/dist/emblems/emblem.registry.js +162 -4
  132. package/dist/emblems/emblem.shapes.d.ts +48 -12
  133. package/dist/emblems/emblem.shapes.js +138 -31
  134. package/dist/emblems/emblem.sprite.d.ts +38 -0
  135. package/dist/emblems/emblem.sprite.js +65 -0
  136. package/dist/emblems/emblem.uri.d.ts +22 -0
  137. package/dist/emblems/emblem.uri.js +29 -0
  138. package/dist/emblems/gear/gear.badmintonracket.d.ts +1 -0
  139. package/dist/emblems/gear/gear.badmintonracket.js +19 -0
  140. package/dist/emblems/gear/gear.baseballglove.d.ts +1 -0
  141. package/dist/emblems/gear/gear.baseballglove.js +21 -0
  142. package/dist/emblems/gear/gear.budo.d.ts +17 -0
  143. package/dist/emblems/gear/gear.budo.js +60 -0
  144. package/dist/emblems/gear/gear.core.d.ts +64 -0
  145. package/dist/emblems/gear/gear.core.js +127 -0
  146. package/dist/emblems/gear/gear.cricketbat.d.ts +1 -0
  147. package/dist/emblems/gear/gear.cricketbat.js +17 -0
  148. package/dist/emblems/gear/gear.field.d.ts +6 -0
  149. package/dist/emblems/gear/gear.field.js +81 -0
  150. package/dist/emblems/gear/gear.fieldhockeystick.d.ts +1 -0
  151. package/dist/emblems/gear/gear.fieldhockeystick.js +16 -0
  152. package/dist/emblems/gear/gear.footballhelmet.d.ts +1 -0
  153. package/dist/emblems/gear/gear.footballhelmet.js +16 -0
  154. package/dist/emblems/gear/gear.goaliemask.d.ts +1 -0
  155. package/dist/emblems/gear/gear.goaliemask.js +23 -0
  156. package/dist/emblems/gear/gear.goalnet.d.ts +1 -0
  157. package/dist/emblems/gear/gear.goalnet.js +25 -0
  158. package/dist/emblems/gear/gear.hockeystick.d.ts +1 -0
  159. package/dist/emblems/gear/gear.hockeystick.js +15 -0
  160. package/dist/emblems/gear/gear.index.d.ts +22 -0
  161. package/dist/emblems/gear/gear.index.js +49 -0
  162. package/dist/emblems/gear/gear.kendo.d.ts +2 -0
  163. package/dist/emblems/gear/gear.kendo.js +41 -0
  164. package/dist/emblems/gear/gear.kyudo.d.ts +2 -0
  165. package/dist/emblems/gear/gear.kyudo.js +31 -0
  166. package/dist/emblems/gear/gear.lacrossestick.d.ts +1 -0
  167. package/dist/emblems/gear/gear.lacrossestick.js +26 -0
  168. package/dist/emblems/gear/gear.rackets.d.ts +4 -0
  169. package/dist/emblems/gear/gear.rackets.js +60 -0
  170. package/dist/emblems/gear/gear.skates.d.ts +3 -0
  171. package/dist/emblems/gear/gear.skates.js +39 -0
  172. package/dist/emblems/gear/gear.sticks.d.ts +3 -0
  173. package/dist/emblems/gear/gear.sticks.js +34 -0
  174. package/dist/emblems/gear/gear.sumo.d.ts +2 -0
  175. package/dist/emblems/gear/gear.sumo.js +43 -0
  176. package/dist/emblems/gear/gear.tabletennispaddle.d.ts +1 -0
  177. package/dist/emblems/gear/gear.tabletennispaddle.js +16 -0
  178. package/dist/emblems/gear/gear.tennisracket.d.ts +1 -0
  179. package/dist/emblems/gear/gear.tennisracket.js +17 -0
  180. package/dist/emblems/gear/gear.track.d.ts +4 -0
  181. package/dist/emblems/gear/gear.track.js +45 -0
  182. package/dist/emblems/gear/gear.water.d.ts +2 -0
  183. package/dist/emblems/gear/gear.water.js +25 -0
  184. package/dist/emblems/medal/bronze.d.ts +2 -0
  185. package/dist/emblems/medal/bronze.js +4 -0
  186. package/dist/emblems/medal/gold.d.ts +2 -0
  187. package/dist/emblems/medal/gold.js +4 -0
  188. package/dist/emblems/medal/place-1.d.ts +2 -0
  189. package/dist/emblems/medal/place-1.js +4 -0
  190. package/dist/emblems/medal/place-2.d.ts +2 -0
  191. package/dist/emblems/medal/place-2.js +4 -0
  192. package/dist/emblems/medal/place-3.d.ts +2 -0
  193. package/dist/emblems/medal/place-3.js +4 -0
  194. package/dist/emblems/medal/silver.d.ts +2 -0
  195. package/dist/emblems/medal/silver.js +4 -0
  196. package/dist/emblems/pennant/championship.d.ts +2 -0
  197. package/dist/emblems/pennant/championship.js +4 -0
  198. package/dist/emblems/sport/afl.d.ts +2 -0
  199. package/dist/emblems/sport/afl.js +12 -0
  200. package/dist/emblems/sport/artisticswimming.d.ts +2 -0
  201. package/dist/emblems/sport/artisticswimming.js +16 -0
  202. package/dist/emblems/sport/athletics.d.ts +2 -0
  203. package/dist/emblems/sport/athletics.js +12 -0
  204. package/dist/emblems/sport/badminton.d.ts +2 -0
  205. package/dist/emblems/sport/badminton.js +13 -0
  206. package/dist/emblems/sport/cfl.d.ts +2 -0
  207. package/dist/emblems/sport/cfl.js +5 -0
  208. package/dist/emblems/sport/cricket.d.ts +2 -0
  209. package/dist/emblems/sport/cricket.js +14 -0
  210. package/dist/emblems/sport/curling.d.ts +2 -0
  211. package/dist/emblems/sport/curling.js +14 -0
  212. package/dist/emblems/sport/diving.d.ts +2 -0
  213. package/dist/emblems/sport/diving.js +18 -0
  214. package/dist/emblems/sport/fieldhockey.d.ts +2 -0
  215. package/dist/emblems/sport/fieldhockey.js +11 -0
  216. package/dist/emblems/sport/gaelic.d.ts +2 -0
  217. package/dist/emblems/sport/gaelic.js +11 -0
  218. package/dist/emblems/sport/handball.d.ts +2 -0
  219. package/dist/emblems/sport/handball.js +15 -0
  220. package/dist/emblems/sport/ifaf.d.ts +2 -0
  221. package/dist/emblems/sport/ifaf.js +5 -0
  222. package/dist/emblems/sport/judo.d.ts +2 -0
  223. package/dist/emblems/sport/judo.js +13 -0
  224. package/dist/emblems/sport/karate.d.ts +2 -0
  225. package/dist/emblems/sport/karate.js +13 -0
  226. package/dist/emblems/sport/kendo.d.ts +2 -0
  227. package/dist/emblems/sport/kendo.js +14 -0
  228. package/dist/emblems/sport/kyudo.d.ts +2 -0
  229. package/dist/emblems/sport/kyudo.js +15 -0
  230. package/dist/emblems/sport/lacrosse.d.ts +2 -0
  231. package/dist/emblems/sport/lacrosse.js +13 -0
  232. package/dist/emblems/sport/mlb.d.ts +2 -0
  233. package/dist/emblems/sport/mlb.js +28 -0
  234. package/dist/emblems/sport/nba.d.ts +2 -0
  235. package/dist/emblems/sport/nba.js +12 -0
  236. package/dist/emblems/sport/netball.d.ts +2 -0
  237. package/dist/emblems/sport/netball.js +14 -0
  238. package/dist/emblems/sport/nfl.d.ts +3 -0
  239. package/dist/emblems/sport/nfl.js +15 -0
  240. package/dist/emblems/sport/nhl.d.ts +2 -0
  241. package/dist/emblems/sport/nhl.js +13 -0
  242. package/dist/emblems/sport/padel.d.ts +2 -0
  243. package/dist/emblems/sport/padel.js +14 -0
  244. package/dist/emblems/sport/pickleball.d.ts +2 -0
  245. package/dist/emblems/sport/pickleball.js +13 -0
  246. package/dist/emblems/sport/racquetball.d.ts +2 -0
  247. package/dist/emblems/sport/racquetball.js +13 -0
  248. package/dist/emblems/sport/roundnet.d.ts +2 -0
  249. package/dist/emblems/sport/roundnet.js +15 -0
  250. package/dist/emblems/sport/rugby.d.ts +2 -0
  251. package/dist/emblems/sport/rugby.js +12 -0
  252. package/dist/emblems/sport/sepaktakraw.d.ts +2 -0
  253. package/dist/emblems/sport/sepaktakraw.js +11 -0
  254. package/dist/emblems/sport/skating.d.ts +2 -0
  255. package/dist/emblems/sport/skating.js +14 -0
  256. package/dist/emblems/sport/soccer.d.ts +2 -0
  257. package/dist/emblems/sport/soccer.js +31 -0
  258. package/dist/emblems/sport/squash.d.ts +2 -0
  259. package/dist/emblems/sport/squash.js +15 -0
  260. package/dist/emblems/sport/sumo.d.ts +2 -0
  261. package/dist/emblems/sport/sumo.js +15 -0
  262. package/dist/emblems/sport/swimming.d.ts +2 -0
  263. package/dist/emblems/sport/swimming.js +15 -0
  264. package/dist/emblems/sport/tabletennis.d.ts +2 -0
  265. package/dist/emblems/sport/tabletennis.js +12 -0
  266. package/dist/emblems/sport/tennis.d.ts +2 -0
  267. package/dist/emblems/sport/tennis.js +15 -0
  268. package/dist/emblems/sport/teqball.d.ts +2 -0
  269. package/dist/emblems/sport/teqball.js +15 -0
  270. package/dist/emblems/sport/volleyball.d.ts +2 -0
  271. package/dist/emblems/sport/volleyball.js +25 -0
  272. package/dist/emblems/sport/waterpolo.d.ts +2 -0
  273. package/dist/emblems/sport/waterpolo.js +15 -0
  274. package/dist/emblems/trophy/banner.d.ts +2 -0
  275. package/dist/emblems/trophy/banner.js +20 -0
  276. package/dist/emblems/trophy/baseball.d.ts +2 -0
  277. package/dist/emblems/trophy/baseball.js +15 -0
  278. package/dist/emblems/trophy/basketball.d.ts +2 -0
  279. package/dist/emblems/trophy/basketball.js +17 -0
  280. package/dist/emblems/trophy/belt.d.ts +2 -0
  281. package/dist/emblems/trophy/belt.js +17 -0
  282. package/dist/emblems/trophy/bowl.d.ts +2 -0
  283. package/dist/emblems/trophy/bowl.js +8 -0
  284. package/dist/emblems/trophy/canadian-bowl.d.ts +2 -0
  285. package/dist/emblems/trophy/canadian-bowl.js +23 -0
  286. package/dist/emblems/trophy/championship-banner.d.ts +2 -0
  287. package/dist/emblems/trophy/championship-banner.js +67 -0
  288. package/dist/emblems/trophy/cricket-urn.d.ts +2 -0
  289. package/dist/emblems/trophy/cricket-urn.js +23 -0
  290. package/dist/emblems/trophy/cup.d.ts +2 -0
  291. package/dist/emblems/trophy/cup.js +16 -0
  292. package/dist/emblems/trophy/football.d.ts +2 -0
  293. package/dist/emblems/trophy/football.js +11 -0
  294. package/dist/emblems/trophy/globe.d.ts +2 -0
  295. package/dist/emblems/trophy/globe.js +9 -0
  296. package/dist/emblems/trophy/hockey-cup.d.ts +2 -0
  297. package/dist/emblems/trophy/hockey-cup.js +22 -0
  298. package/dist/emblems/trophy/laurel.d.ts +2 -0
  299. package/dist/emblems/trophy/laurel.js +40 -0
  300. package/dist/emblems/trophy/lidded-cup.d.ts +2 -0
  301. package/dist/emblems/trophy/lidded-cup.js +21 -0
  302. package/dist/emblems/trophy/plaque.d.ts +2 -0
  303. package/dist/emblems/trophy/plaque.js +17 -0
  304. package/dist/emblems/trophy/ring.d.ts +2 -0
  305. package/dist/emblems/trophy/ring.js +30 -0
  306. package/dist/emblems/trophy/rosette.d.ts +2 -0
  307. package/dist/emblems/trophy/rosette.js +27 -0
  308. package/dist/emblems/trophy/rugby-cup.d.ts +2 -0
  309. package/dist/emblems/trophy/rugby-cup.js +23 -0
  310. package/dist/emblems/trophy/salver.d.ts +2 -0
  311. package/dist/emblems/trophy/salver.js +9 -0
  312. package/dist/emblems/trophy/soccer-ball.d.ts +2 -0
  313. package/dist/emblems/trophy/soccer-ball.js +9 -0
  314. package/dist/emblems/trophy/soccer-globe.d.ts +2 -0
  315. package/dist/emblems/trophy/soccer-globe.js +18 -0
  316. package/dist/emblems/trophy/sumo-cup.d.ts +2 -0
  317. package/dist/emblems/trophy/sumo-cup.js +28 -0
  318. package/dist/emblems/trophy/tennis-cup.d.ts +2 -0
  319. package/dist/emblems/trophy/tennis-cup.js +24 -0
  320. package/dist/emblems/trophy/tennis-plate.d.ts +2 -0
  321. package/dist/emblems/trophy/tennis-plate.js +16 -0
  322. package/dist/emblems-entry.d.ts +20 -7
  323. package/dist/emblems-entry.js +8 -2
  324. package/dist/index.d.ts +131 -1
  325. package/dist/index.js +131 -3
  326. package/dist/turn-control.d.ts +101 -0
  327. package/dist/turn-control.js +363 -0
  328. package/dist/turn-entry.d.ts +2 -0
  329. package/dist/turn-entry.js +1 -0
  330. package/dist/version.d.ts +1 -1
  331. package/dist/version.js +1 -1
  332. package/package.json +33 -7
  333. package/LICENSES/Apache-2.0.txt +0 -55
  334. package/LICENSES/CC-BY-3.0.md +0 -15
  335. package/dist/emblems/ball/soccer.d.ts +0 -2
  336. package/dist/emblems/ball/soccer.js +0 -9
  337. package/dist/emblems/emblem.ball.d.ts +0 -28
  338. package/dist/emblems/emblem.ball.js +0 -70
@@ -1,7 +1,8 @@
1
1
  import { EMBLEM_STYLES } from "./emblem.core.js";
2
- import { BALL_IDS, EMBLEM_IDS } from "./emblem.ids.js";
2
+ import { BALL_IDS, CREST_SHAPES, EMBLEM_ALIASES, EMBLEM_IDS } from "./emblem.ids.js";
3
+ import { EMBLEM_DESCRIPTIONS } from "./emblem.descriptions.js";
3
4
  import { EMBLEM_TABLE } from "./emblem.registry.js";
4
- /** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`. */
5
+ /** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`, and a trophy or an award may be written without its group (`cup`, `crown`). */
5
6
  export function parseEmblem(value) {
6
7
  if (typeof value !== "string")
7
8
  return undefined;
@@ -17,9 +18,10 @@ export function parseEmblem(value) {
17
18
  style = tail;
18
19
  text = text.slice(0, slash);
19
20
  }
20
- return Object.hasOwn(EMBLEM_TABLE, text) ? { id: text, style } : undefined;
21
+ const id = Object.hasOwn(EMBLEM_ALIASES, text) ? EMBLEM_ALIASES[text] : text;
22
+ return Object.hasOwn(EMBLEM_TABLE, id) ? { id: id, style } : undefined;
21
23
  }
22
- /** True when the value is the id of an emblem (with no style). */
24
+ /** True when the value is the id of an emblem (not a short name, and with no style). */
23
25
  export function isEmblemId(value) {
24
26
  return typeof value === "string" && Object.hasOwn(EMBLEM_TABLE, value);
25
27
  }
@@ -29,7 +31,7 @@ export function emblemOf(ref) {
29
31
  return { emblem: ref, style: undefined };
30
32
  const parsed = parseEmblem(ref);
31
33
  if (parsed === undefined)
32
- throw new Error(`Unknown emblem "${ref.slice(0, 60)}". Ids look like "award:medal" or "ball:soccer"; see EMBLEM_IDS.`);
34
+ throw new Error(`Unknown emblem "${ref.slice(0, 60)}". Ids look like "trophy:cup", "medal:gold", "sport:nhl" or "crest:shield"; see EMBLEM_IDS.`);
33
35
  return { emblem: EMBLEM_TABLE[parsed.id], style: parsed.style };
34
36
  }
35
37
  const withStyle = (style, options) => (style === undefined || options?.style !== undefined ? options : { ...options, style });
@@ -39,8 +41,8 @@ const withStyle = (style, options) => (style === undefined || options?.style !==
39
41
  * @example
40
42
  * ```ts
41
43
  * import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
42
- * const svg = renderEmblem("award:medal", { style: "line", size: 32 });
43
- * console.log(svg.startsWith("<svg"), svg.includes("<title>Medal</title>"));
44
+ * const svg = renderEmblem("trophy:cup", { style: "line", size: 32 });
45
+ * console.log(svg.startsWith("<svg"), svg.includes("<title>Cup</title>"));
44
46
  * // true true
45
47
  * ```
46
48
  */
@@ -51,11 +53,11 @@ export function renderEmblem(ref, options) {
51
53
  /** The same as `renderEmblem`. */
52
54
  export const emblemSvg = renderEmblem;
53
55
  /**
54
- * An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A flat emblem (a medal) flips like a coin and shows its back; a ball rolls.
56
+ * An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A cup, bowl or urn keeps its outline and moves its light, handles and seams; a medal flips like a coin and shows its back; a ball rolls; an icon is not turned.
55
57
  * @example
56
58
  * ```ts
57
59
  * import { emblemFrame, renderEmblem } from "@johnmorrisdotca/dougu-sports/turn";
58
- * console.log(emblemFrame("award:medal", { yaw: 0 }) === renderEmblem("award:medal"));
60
+ * console.log(emblemFrame("medal:gold", { yaw: 0 }) === renderEmblem("medal:gold"));
59
61
  * // true
60
62
  * ```
61
63
  */
@@ -76,7 +78,9 @@ export const EMBLEMS = Object.freeze(Object.fromEntries(EMBLEM_IDS.map((id) => [
76
78
  /** The names, source and kind of an emblem. */
77
79
  export function emblemInfo(id) {
78
80
  const e = EMBLEM_TABLE[id];
79
- return { id, en: e.en, ja: e.ja, source: e.source, kind: e.kind };
81
+ const size = e.size;
82
+ const description = EMBLEM_DESCRIPTIONS[id];
83
+ return { id, en: e.en, ja: e.ja, source: e.source, kind: e.kind, ...(size === undefined ? {} : { size }), ...(description === undefined ? {} : { description }) };
80
84
  }
81
85
  /** An emblem's name in a language. */
82
86
  export function emblemName(id, language = "en") {
@@ -86,3 +90,45 @@ export function emblemName(id, language = "en") {
86
90
  export function emblemModel(id) {
87
91
  return EMBLEM_TABLE[id].model;
88
92
  }
93
+ /**
94
+ * A generic crest tinted by a team's colours, with its letters if it has any: what a team with no logo gets. The letters are in the ink that reads on the colour.
95
+ * @example
96
+ * ```ts
97
+ * import { crest } from "@johnmorrisdotca/dougu-sports/emblems";
98
+ * const svg = crest({ shape: "shield", colors: ["#c8102e", "#f4f0e4"], initials: "NO" });
99
+ * console.log(svg.includes(">NO<"));
100
+ * // true
101
+ * ```
102
+ */
103
+ export function crest(options = {}) {
104
+ const colors = typeof options.colors === "string" ? [options.colors] : (options.colors ?? []);
105
+ const shape = CREST_SHAPES.includes(options.shape) ? options.shape : "shield";
106
+ return EMBLEM_TABLE[`crest:${shape}`].svg({ tint: colors[0], accent: colors[1], initials: options.initials, size: options.size, style: options.style, theme: options.theme, locale: options.locale, title: options.title });
107
+ }
108
+ /** A medal on a ribbon: `medal("gold")`, `"silver"` or `"bronze"`; any other kind is the gold one. */
109
+ export function medal(kind, options) {
110
+ return (EMBLEM_TABLE[`medal:${kind}`] ?? EMBLEM_TABLE["medal:gold"]).svg(options);
111
+ }
112
+ /** The icon of a sport, by the names of `SPORT_NAMES`: `sportIcon("nhl")`. An unknown sport is an error. */
113
+ export function sportIcon(sport, options) {
114
+ const e = Object.hasOwn(EMBLEM_TABLE, `sport:${sport}`) ? EMBLEM_TABLE[`sport:${sport}`] : undefined;
115
+ if (e === undefined)
116
+ throw new Error(`Unknown sport "${String(sport).slice(0, 40)}": the icons are for the names in SPORT_NAMES.`);
117
+ return e.svg(options);
118
+ }
119
+ /**
120
+ * A felt championship pennant with a stitched edge, lettered with its words and its year.
121
+ * @example
122
+ * ```ts
123
+ * import { pennant } from "@johnmorrisdotca/dougu-sports/emblems";
124
+ * const svg = pennant({ colors: ["#1f4e8c", "#f2c230"], text: "Champions", year: 2026 });
125
+ * console.log(svg.includes(">CHAMPIONS<"), svg.includes(">2026<"));
126
+ * // true true
127
+ * ```
128
+ */
129
+ export function pennant(options = {}) {
130
+ const colors = typeof options.colors === "string" ? [options.colors] : (options.colors ?? []);
131
+ const o = { tint: colors[0], accent: colors[1], numberColor: colors[2], engrave: options.text, label: options.label, rank: options.rank, year: options.year, view: options.view, size: options.size, style: options.style, theme: options.theme, yaw: options.yaw, pitch: options.pitch };
132
+ const e = EMBLEM_TABLE["pennant:championship"];
133
+ return options.yaw === undefined && options.pitch === undefined ? e.svg(o) : e.frame(o);
134
+ }
@@ -0,0 +1,31 @@
1
+ /** An emblem's document taken apart. */
2
+ export interface Parts {
3
+ /** The view box, `0 0 64 64` unless the drawing came from elsewhere. */
4
+ box: string;
5
+ /** The definitions, one string for each top-level element of the `<defs>` (a gradient, a clip path, a filter), with the id it carries. */
6
+ defs: readonly {
7
+ id: string;
8
+ text: string;
9
+ }[];
10
+ /** Everything that draws: the body, with the `<title>`, `<style>` and `<defs>` taken out. A `<desc>` stays, because it carries the credit of copied art. */
11
+ body: string;
12
+ }
13
+ /** Takes an emblem's document apart. */
14
+ export declare function partsOf(svg: string): Parts;
15
+ /**
16
+ * Documents put together: the definitions of all of them in one list with none twice, and every id renamed so that two different definitions never share one. With a `prefix` the ids are the prefix and a short
17
+ * counter, so a sheet's ids cannot meet the page's own; with none an id keeps its name until a different definition wants it.
18
+ */
19
+ export declare class IdSpace {
20
+ private readonly named;
21
+ private readonly taken;
22
+ private readonly prefix;
23
+ private count;
24
+ readonly defs: string[];
25
+ constructor(prefix?: string);
26
+ private fresh;
27
+ /** Takes one document's parts in: its definitions join the list, and its body comes back with the ids it uses. */
28
+ add(parts: Parts): string;
29
+ }
30
+ /** A document nested inside another: its box becomes the place the parent gives it. */
31
+ export declare function nest(box: string, body: string, x: number, y: number, width: number, height: number): string;
@@ -0,0 +1,91 @@
1
+ // The pieces that the sprite, the podium and the award case share: an emblem's document taken apart (its view box, its definitions, its body), and put together again inside another document with
2
+ // every id unique. The emblems are written by this package, so the parts are found by their shape, not by a general XML parser.
3
+ /** The top-level elements of a run of markup, each with its `id` attribute (an empty string when it has none). */
4
+ function topLevel(markup) {
5
+ const out = [];
6
+ const tag = /<(\/?)[A-Za-z][\w:-]*[^>]*?(\/?)>/g;
7
+ let depth = 0;
8
+ let start = 0;
9
+ for (let m = tag.exec(markup); m !== null; m = tag.exec(markup)) {
10
+ if (m[1] === "/") {
11
+ depth--;
12
+ if (depth === 0)
13
+ out.push({ id: "", text: markup.slice(start, m.index + m[0].length) });
14
+ }
15
+ else if (m[2] === "/") {
16
+ if (depth === 0)
17
+ out.push({ id: "", text: m[0] });
18
+ }
19
+ else {
20
+ if (depth === 0)
21
+ start = m.index;
22
+ depth++;
23
+ }
24
+ }
25
+ return out.map((e) => ({ id: /\sid="([^"]*)"/.exec(e.text)?.[1] ?? "", text: e.text }));
26
+ }
27
+ /** Takes an emblem's document apart. */
28
+ export function partsOf(svg) {
29
+ const open = /^<svg\s[^>]*>/.exec(svg);
30
+ const box = (open === null ? undefined : /\sviewBox="([^"]+)"/.exec(open[0])?.[1]) ?? "0 0 64 64";
31
+ let inner = open === null ? svg : svg.slice(open[0].length, svg.lastIndexOf("</svg>"));
32
+ inner = inner.replace(/<title>[^<]*<\/title>/, "").replace(/<style>[^<]*<\/style>/, "");
33
+ const defs = [];
34
+ inner = inner.replace(/<defs>([\s\S]*?)<\/defs>/g, (_, content) => {
35
+ defs.push(...topLevel(content));
36
+ return "";
37
+ });
38
+ return { box, defs, body: inner };
39
+ }
40
+ /** The ids a document of ours refers to: `id="x"`, `url(#x)` and `href="#x"`. */
41
+ const REFERENCE = /(\sid="|url\(#|href="#)([^")]+)/g;
42
+ /**
43
+ * Documents put together: the definitions of all of them in one list with none twice, and every id renamed so that two different definitions never share one. With a `prefix` the ids are the prefix and a short
44
+ * counter, so a sheet's ids cannot meet the page's own; with none an id keeps its name until a different definition wants it.
45
+ */
46
+ export class IdSpace {
47
+ named = new Map();
48
+ taken = new Set();
49
+ prefix;
50
+ count = 0;
51
+ defs = [];
52
+ constructor(prefix = "") {
53
+ this.prefix = prefix;
54
+ }
55
+ fresh(id) {
56
+ if (this.prefix === "") {
57
+ let candidate = id;
58
+ while (this.taken.has(candidate))
59
+ candidate = `${id}-${(++this.count).toString(36)}`;
60
+ return candidate;
61
+ }
62
+ return `${this.prefix}_${(this.count++).toString(36)}`;
63
+ }
64
+ /** Takes one document's parts in: its definitions join the list, and its body comes back with the ids it uses. */
65
+ add(parts) {
66
+ const rename = new Map();
67
+ const added = [];
68
+ for (const def of parts.defs) {
69
+ if (def.id === "")
70
+ continue;
71
+ const key = `${def.id}\u0000${def.text}`;
72
+ let name = this.named.get(key);
73
+ if (name === undefined) {
74
+ name = this.fresh(def.id);
75
+ this.taken.add(name);
76
+ this.named.set(key, name);
77
+ added.push(def.text);
78
+ }
79
+ rename.set(def.id, name);
80
+ }
81
+ const apply = (text) => text.replace(REFERENCE, (all, lead, id) => (rename.has(id) ? `${lead}${rename.get(id)}` : all));
82
+ for (const text of added)
83
+ this.defs.push(apply(text));
84
+ return apply(parts.body);
85
+ }
86
+ }
87
+ /** A document nested inside another: its box becomes the place the parent gives it. */
88
+ export function nest(box, body, x, y, width, height) {
89
+ const n = (v) => String(Math.round(v * 100) / 100 + 0);
90
+ return `<svg x="${n(x)}" y="${n(y)}" width="${n(width)}" height="${n(height)}" viewBox="${box}">${body}</svg>`;
91
+ }
@@ -6,6 +6,8 @@ export declare const EMBLEM_STYLES: readonly ["metal", "line", "color"];
6
6
  * one, for an image (an `<img>`, a data address) that cannot inherit. `light` and `dark` force one.
7
7
  */
8
8
  export type EmblemTheme = "inherit" | "auto" | "light" | "dark";
9
+ /** The languages an emblem's `<title>` can be written in. */
10
+ export type EmblemLocale = "en" | "ja";
9
11
  export interface EmblemOptions {
10
12
  /** `metal` (the default), `line` or `color`. */
11
13
  style?: EmblemStyle;
@@ -15,11 +17,40 @@ export interface EmblemOptions {
15
17
  tint?: string;
16
18
  /** `inherit` (the default), `auto`, `light` or `dark`. */
17
19
  theme?: EmblemTheme;
20
+ /** A second colour: a medal's ribbon, a crest's band, the flags of a trophy. A hex colour or `rgb()`; anything else is ignored. */
21
+ accent?: string;
22
+ /** The letters of a crest, up to three. */
23
+ initials?: string;
24
+ /** A ball: force the grain of its surface on or off. By default it is on for a ball of 48 pixels or more that is not turning. */
25
+ grain?: boolean;
26
+ /** The language of the `<title>`: `"en"` (the default) or `"ja"`, from the emblem's English or Japanese name. */
27
+ locale?: EmblemLocale;
28
+ /** The `<title>`: a string writes that title (escaped); `false` drops it and marks the drawing `aria-hidden="true"`, for an emblem that sits beside text that says the same. */
29
+ title?: string | false;
30
+ /**
31
+ * Text cut into the face of a medal or place badge, the plaque, the belt, and the plinth of a cup: any text, Japanese included, up to three lines (a line break, or a space between a word and a year, makes lines).
32
+ * It wins over `label`, `year` and `rank`.
33
+ */
34
+ engrave?: string;
35
+ /** The words to engrave ("MVP"), with `year` and `rank` as lines of their own. Ignored when `engrave` is given. */
36
+ label?: string;
37
+ /** A year, engraved small under the label (on a plaque, on its nameplate). A number or a string. */
38
+ year?: number | string;
39
+ /** A place or a number, engraved large ("1"). On a place badge it is the badge's own place unless given. */
40
+ rank?: number | string;
41
+ /** The engraving of a medal's back, shown when it is turned over. Without it the back is plain. */
42
+ engraveBack?: string;
43
+ /** The colour of a pennant's lettering when it is not the second colour. A hex colour or `rgb()`. */
44
+ numberColor?: string;
45
+ /** Which side of a pennant is drawn at rest: `"front"` (the default) or `"back"`. */
46
+ view?: "front" | "back";
18
47
  }
19
48
  /** A turn, in degrees from the resting view (0 and 0 is the still drawing): `yaw` about the vertical axis, `pitch` the tilt toward the eye. */
20
49
  export interface FrameOptions extends EmblemOptions {
21
50
  yaw?: number;
22
51
  pitch?: number;
52
+ /** A ball: the turn about the line of sight. */
53
+ roll?: number;
23
54
  }
24
55
  /** The ink of a drawing when a theme sets it, and the page it is made to read on. */
25
56
  export declare const EMBLEM_INK: {
@@ -36,11 +67,12 @@ export declare const METALS: {
36
67
  readonly silver: "#aeb6c0";
37
68
  readonly bronze: "#b8733a";
38
69
  };
39
- export type Metal = keyof typeof METALS;
40
- /** Where an emblem's art comes from: drawn for this package (`ours`) or taken from a source listed in NOTICE.md. */
41
- export type EmblemSource = "ours" | "material" | "noto" | "mdi" | "game-icons";
42
- /** What an emblem is: a flat object (a front and a back, to flip), a ball (marks on a sphere, to roll), a body of revolution (`lathe`) or an icon (one path, not turned). */
43
- export type EmblemKind = "flat" | "ball" | "lathe" | "icon";
70
+ /** A metal by name, or `flat` for a colour that is no metal (a crest's blue, a sport's plain ink). */
71
+ export type Metal = keyof typeof METALS | "flat";
72
+ /** Where an emblem's art comes from: drawn for this package (`ours`, `drawn`) or made by this package's own code (`generated`). Nothing is copied from another project. */
73
+ export type EmblemSource = "ours" | "generated" | "drawn";
74
+ /** What an emblem is: a flat object (a front and a back, to flip), a ball (a sphere or a solid, turned in 3D), a body of revolution (`lathe`), an icon (one drawing, not turned) or a piece of gear (a flat drawing, not turned). */
75
+ export type EmblemKind = "flat" | "ball" | "lathe" | "icon" | "gear";
44
76
  export type Rgb = readonly [number, number, number];
45
77
  /** A colour from `#rgb`, `#rrggbb` or `rgb(r, g, b)`, or `undefined` for anything else. */
46
78
  export declare function readColour(value: string | undefined): Rgb | undefined;
@@ -49,6 +81,19 @@ export declare const hexOf: (rgb: Rgb) => string;
49
81
  export declare function mix(rgb: Rgb, amount: number): string;
50
82
  /** Text made safe to write between tags and inside a double-quoted attribute. */
51
83
  export declare const escape: (text: string) => string;
84
+ /**
85
+ * The `<title>` of a finished drawing, as the options ask: a string is the title (escaped), `false` drops it and hides the drawing from a screen reader, and `locale: "ja"` writes the Japanese name. With none
86
+ * of the three the drawing is returned as it is.
87
+ */
88
+ export declare function relabel(svg: string, en: string, ja: string, o: {
89
+ locale?: unknown;
90
+ title?: unknown;
91
+ } | undefined): string;
92
+ /** A drawing function whose result carries the title the options ask for. */
93
+ export declare const labelled: <O extends {
94
+ locale?: unknown;
95
+ title?: unknown;
96
+ }>(en: string, ja: string, draw: (options?: O) => string) => (options?: O) => string;
52
97
  /** A number written for a path: two decimals at most, and never `-0`. */
53
98
  export declare const n2: (value: number) => string;
54
99
  /** The options as the renderers use them. */
@@ -57,10 +102,26 @@ export interface Resolved {
57
102
  size: number;
58
103
  theme: EmblemTheme;
59
104
  tint: Rgb | undefined;
105
+ accent: string | undefined;
106
+ initials: string;
60
107
  }
61
108
  export declare function resolve(o: EmblemOptions | undefined): Resolved;
109
+ /** What is to be cut into a face: the free text, or the label, year and rank, and the text of the back. A line is at most 24 letters and has no control character. */
110
+ export interface Engraving {
111
+ free?: string;
112
+ label?: string;
113
+ year?: string;
114
+ rank?: string;
115
+ back?: string;
116
+ }
117
+ /** A text from outside made safe: control characters removed, at most 24 letters a line and `lines` lines, or `undefined` when nothing is left. */
118
+ export declare const clean: (value: unknown, lines?: number) => string | undefined;
62
119
  /** The main colour of a metal, or the tint when there is one. */
63
120
  export declare const mainOf: (metal: Metal, tint: Rgb | undefined) => Rgb;
121
+ /** The relative luminance of a colour, 0 to 1. */
122
+ export declare function lum(rgb: Rgb): number;
123
+ /** Black or white, whichever reads better on a colour. */
124
+ export declare const onColour: (rgb: Rgb) => string;
64
125
  /** A turn in degrees, as a finite number (0 for anything else). */
65
126
  export declare const degrees: (value: number | undefined) => number;
66
127
  /** The colours a drawing is painted with. In the `line` style every fill is `none`. */
@@ -74,8 +135,27 @@ export interface Paint {
74
135
  /** The definitions the fills refer to. */
75
136
  defs: string;
76
137
  }
77
- /** The paint for a main colour in a style. The gradient's id names the colour, so two of one colour in a page agree. */
78
- export declare function paintFor(style: EmblemStyle, main: Rgb, kind?: "linear" | "radial"): Paint;
138
+ /** The paint of a ball: a radial gradient in the metal style. The gradient's id names the colour, so two of one colour in a page agree. */
139
+ export declare function paintFor(style: EmblemStyle, main: Rgb): Paint;
140
+ /** A gradient: its id, its definition (a fragment for a `<defs>`) and the fill that names it. */
141
+ export interface Gradient {
142
+ id: string;
143
+ def: string;
144
+ fill: string;
145
+ }
146
+ /**
147
+ * The shading of a round metal body: a dark edge, a bright band left of the middle, the metal, a darker side, and a faint light from the rim on the far edge, as polished metal throws it. `shift` slides the bright
148
+ * band (a turn). The id names the colour and the shift, so two bodies of one colour in a page share one definition.
149
+ */
150
+ export declare function cylinderGradient(main: Rgb, shift?: number): Gradient;
151
+ /** The shading of a round flat or a ball: light from the top left, the metal, then dark at the far edge. */
152
+ export declare function orbGradient(main: Rgb): Gradient;
153
+ /** The shading of a flat sheet of metal, from a bright corner to a dark one. */
154
+ export declare function sheetGradient(main: Rgb): Gradient;
155
+ /** The shading of a raised rim: bright on the top left, dark on the bottom right, as a bevel catches the light (or the other way round, for a groove). */
156
+ export declare function bevelGradient(main: Rgb, groove?: boolean): Gradient;
157
+ /** The gradients' definitions as one `<defs>`, with none twice. */
158
+ export declare const defsOf: (gradients: readonly Gradient[]) => string;
79
159
  /** A drawing wrapped into a document: the title, the outline's colour for the theme, and the group that strokes it. */
80
160
  export declare function wrap(o: {
81
161
  title: string;
@@ -85,6 +165,8 @@ export declare function wrap(o: {
85
165
  defs?: string;
86
166
  body: string;
87
167
  box?: string;
168
+ edge?: string;
169
+ width?: number;
88
170
  }): string;
89
171
  /** One emblem: its id and names, where its art comes from, and the functions that draw it. Importing one of these pulls in its own module and the small renderer it needs, not the other emblems. */
90
172
  export interface Emblem<Model = unknown> {
@@ -29,20 +29,62 @@ export function mix(rgb, amount) {
29
29
  }
30
30
  /** Text made safe to write between tags and inside a double-quoted attribute. */
31
31
  export const escape = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
32
+ /**
33
+ * The `<title>` of a finished drawing, as the options ask: a string is the title (escaped), `false` drops it and hides the drawing from a screen reader, and `locale: "ja"` writes the Japanese name. With none
34
+ * of the three the drawing is returned as it is.
35
+ */
36
+ export function relabel(svg, en, ja, o) {
37
+ const title = o?.title;
38
+ const japanese = o?.locale === "ja";
39
+ if (title === false)
40
+ return svg.replace(/<title>[^<]*<\/title>/, "").replace(' role="img"', ' aria-hidden="true"');
41
+ const custom = typeof title === "string" && title.trim() !== "";
42
+ if (!custom && !japanese)
43
+ return svg;
44
+ const text = custom ? title.trim().slice(0, 300) : ja;
45
+ const titled = svg.replace(/<title>[^<]*<\/title>/, () => `<title>${escape(text)}</title>`);
46
+ return custom ? titled : titled.replace(' role="img"', ' role="img" lang="ja"');
47
+ }
48
+ /** A drawing function whose result carries the title the options ask for. */
49
+ export const labelled = (en, ja, draw) => (options) => relabel(draw(options), en, ja, options);
32
50
  /** A number written for a path: two decimals at most, and never `-0`. */
33
51
  export const n2 = (value) => String(Math.round(value * 100) / 100 + 0);
34
52
  export function resolve(o) {
35
53
  const size = typeof o?.size === "number" && Number.isFinite(o.size) && o.size > 0 ? Math.min(Math.round(o.size * 100) / 100, 4096) : 64;
36
54
  const theme = o?.theme === "auto" || o?.theme === "light" || o?.theme === "dark" ? o.theme : "inherit";
37
55
  const style = o?.style === "line" || o?.style === "color" ? o.style : "metal";
38
- return { style, size, theme, tint: readColour(o?.tint) };
56
+ const accent = readColour(o?.accent);
57
+ const initials = typeof o?.initials === "string" ? [...o.initials.trim()].slice(0, 3).join("").toUpperCase() : "";
58
+ return { style, size, theme, tint: readColour(o?.tint), accent: accent === undefined ? undefined : hexOf(accent), initials };
39
59
  }
60
+ /** A text from outside made safe: control characters removed, at most 24 letters a line and `lines` lines, or `undefined` when nothing is left. */
61
+ export const clean = (value, lines = 1) => {
62
+ if (typeof value !== "string" && typeof value !== "number")
63
+ return undefined;
64
+ const text = String(value)
65
+ .split(/\r?\n/)
66
+ .slice(0, lines)
67
+ .map((line) => [...line.replace(/\p{Cc}/gu, "").trim()].slice(0, 24).join(""))
68
+ .filter((line) => line !== "")
69
+ .join("\n");
70
+ return text === "" ? undefined : text;
71
+ };
40
72
  /** The main colour of a metal, or the tint when there is one. */
41
- export const mainOf = (metal, tint) => tint ?? readColour(METALS[metal]);
73
+ export const mainOf = (metal, tint) => tint ?? readColour(metal === "flat" ? "#8a949e" : METALS[metal]);
74
+ /** The relative luminance of a colour, 0 to 1. */
75
+ export function lum(rgb) {
76
+ const [r, g, b] = rgb.map((c) => {
77
+ const k = c / 255;
78
+ return k <= 0.03928 ? k / 12.92 : ((k + 0.055) / 1.055) ** 2.4;
79
+ });
80
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
81
+ }
82
+ /** Black or white, whichever reads better on a colour. */
83
+ export const onColour = (rgb) => ((lum(rgb) + 0.05) / 0.05 > 1.05 / (lum(rgb) + 0.05) ? "#000000" : "#ffffff");
42
84
  /** A turn in degrees, as a finite number (0 for anything else). */
43
85
  export const degrees = (value) => (typeof value === "number" && Number.isFinite(value) ? value % 360 : 0);
44
- /** The paint for a main colour in a style. The gradient's id names the colour, so two of one colour in a page agree. */
45
- export function paintFor(style, main, kind = "linear") {
86
+ /** The paint of a ball: a radial gradient in the metal style. The gradient's id names the colour, so two of one colour in a page agree. */
87
+ export function paintFor(style, main) {
46
88
  if (style === "line")
47
89
  return { main: "none", shade: "none", light: "none", ribbon: "none", defs: "" };
48
90
  const shade = mix(main, -0.28);
@@ -50,18 +92,50 @@ export function paintFor(style, main, kind = "linear") {
50
92
  const ribbon = "#b3362b";
51
93
  if (style === "color")
52
94
  return { main: hexOf(main), shade, light, ribbon, defs: "" };
53
- const id = `dgs${kind === "radial" ? "r" : "l"}${hexOf(main).slice(1)}`;
54
- const stops = `<stop offset="0" stop-color="${mix(main, -0.3)}"/><stop offset="0.3" stop-color="${light}"/><stop offset="0.55" stop-color="${hexOf(main)}"/><stop offset="1" stop-color="${mix(main, -0.38)}"/>`;
55
- const defs = kind === "linear"
56
- ? `<defs><linearGradient id="${id}" x2="1" y2="0.2">${stops}</linearGradient></defs>`
57
- : `<defs><radialGradient id="${id}" cx="0.36" cy="0.3" r="0.8"><stop offset="0" stop-color="${light}"/><stop offset="0.55" stop-color="${hexOf(main)}"/><stop offset="1" stop-color="${mix(main, -0.38)}"/></radialGradient></defs>`;
95
+ const id = `dgsr${hexOf(main).slice(1)}`;
96
+ const defs = `<defs><radialGradient id="${id}" cx="0.36" cy="0.3" r="0.8"><stop offset="0" stop-color="${light}"/><stop offset="0.55" stop-color="${hexOf(main)}"/><stop offset="1" stop-color="${mix(main, -0.38)}"/></radialGradient></defs>`;
58
97
  return { main: `url(#${id})`, shade, light, ribbon, defs };
59
98
  }
99
+ const stops = (list) => list.map(([at, colour]) => `<stop offset="${n2(at).replace(/^0\./, ".")}" stop-color="${colour}"/>`).join("");
100
+ /**
101
+ * The shading of a round metal body: a dark edge, a bright band left of the middle, the metal, a darker side, and a faint light from the rim on the far edge, as polished metal throws it. `shift` slides the bright
102
+ * band (a turn). The id names the colour and the shift, so two bodies of one colour in a page share one definition.
103
+ */
104
+ export function cylinderGradient(main, shift = 0) {
105
+ const h = Math.max(0.14, Math.min(0.5, 0.3 + shift));
106
+ const id = `dgsc${hexOf(main).slice(1)}${shift === 0 ? "" : `s${Math.round(shift * 100) + 100}`}`;
107
+ const list = [[0, mix(main, -0.5)], [0.1, mix(main, -0.16)], [h, mix(main, 0.62)], [h + 0.26, mix(main, 0.08)], [0.84, mix(main, -0.36)], [0.95, mix(main, -0.1)], [1, mix(main, -0.52)]];
108
+ return { id, def: `<linearGradient id="${id}">${stops(list)}</linearGradient>`, fill: `url(#${id})` };
109
+ }
110
+ /** The shading of a round flat or a ball: light from the top left, the metal, then dark at the far edge. */
111
+ export function orbGradient(main) {
112
+ const id = `dgso${hexOf(main).slice(1)}`;
113
+ return { id, def: `<radialGradient id="${id}" cx="0.36" cy="0.3" r="0.82">${stops([[0, mix(main, 0.7)], [0.3, mix(main, 0.2)], [0.62, hexOf(main)], [1, mix(main, -0.42)]])}</radialGradient>`, fill: `url(#${id})` };
114
+ }
115
+ /** The shading of a flat sheet of metal, from a bright corner to a dark one. */
116
+ export function sheetGradient(main) {
117
+ const id = `dgsd${hexOf(main).slice(1)}`;
118
+ return { id, def: `<linearGradient id="${id}" x2="1" y2="1">${stops([[0, mix(main, 0.55)], [0.35, mix(main, 0.12)], [0.6, hexOf(main)], [1, mix(main, -0.4)]])}</linearGradient>`, fill: `url(#${id})` };
119
+ }
120
+ /** The shading of a raised rim: bright on the top left, dark on the bottom right, as a bevel catches the light (or the other way round, for a groove). */
121
+ export function bevelGradient(main, groove = false) {
122
+ const id = `dgse${hexOf(main).slice(1)}${groove ? "g" : ""}`;
123
+ const [a, b] = groove ? [mix(main, -0.45), mix(main, 0.6)] : [mix(main, 0.65), mix(main, -0.5)];
124
+ return { id, def: `<linearGradient id="${id}" x2="1" y2="1">${stops([[0, a], [0.5, hexOf(main)], [1, b]])}</linearGradient>`, fill: `url(#${id})` };
125
+ }
126
+ /** The gradients' definitions as one `<defs>`, with none twice. */
127
+ export const defsOf = (gradients) => {
128
+ const seen = new Set();
129
+ const list = gradients.filter((g) => !seen.has(g.id) && seen.add(g.id));
130
+ return list.length === 0 ? "" : `<defs>${list.map((g) => g.def).join("")}</defs>`;
131
+ };
60
132
  /** A drawing wrapped into a document: the title, the outline's colour for the theme, and the group that strokes it. */
61
133
  export function wrap(o) {
62
134
  const colour = o.theme === "dark" ? EMBLEM_INK.dark : o.theme === "inherit" ? "" : EMBLEM_INK.light;
63
135
  const auto = o.theme === "auto" ? `<style>@media(prefers-color-scheme:dark){svg{color:${EMBLEM_INK.dark}}}</style>` : "";
64
- const stroke = o.style === "line" ? 2.6 : 2.2;
136
+ // `edge` is a colour of the drawing's own for the outline (a metal's darker tone); without it the outline is the page's ink. The `line` style is always the page's ink.
137
+ const ink = o.edge !== undefined && o.style !== "line" ? o.edge : "currentColor";
138
+ const stroke = o.width ?? (o.style === "line" ? 2.6 : 2.2);
65
139
  return (`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${o.box ?? "0 0 64 64"}" width="${o.size}" height="${o.size}" role="img"${colour === "" ? "" : ` color="${colour}"`}>` +
66
- `<title>${escape(o.title)}</title>${auto}${o.defs ?? ""}<g fill="none" stroke="currentColor" stroke-width="${stroke}" stroke-linejoin="round" stroke-linecap="round">${o.body}</g></svg>`);
140
+ `<title>${escape(o.title)}</title>${auto}${o.defs ?? ""}<g fill="none" stroke="${ink}" stroke-width="${n2(stroke)}" stroke-linejoin="round" stroke-linecap="round">${o.body}</g></svg>`);
67
141
  }
@@ -0,0 +1,7 @@
1
+ import type { EmblemId } from "./emblem.ids.ts";
2
+ /** An emblem's description in the two languages. */
3
+ export interface EmblemDescription {
4
+ readonly en: string;
5
+ readonly ja: string;
6
+ }
7
+ export declare const EMBLEM_DESCRIPTIONS: Readonly<Partial<Record<EmblemId, EmblemDescription>>>;
@@ -0,0 +1,60 @@
1
+ export const EMBLEM_DESCRIPTIONS = {
2
+ "trophy:hockey-cup": { en: "Tall banded silver cup", ja: "帯を何段も重ねた背の高い銀のカップ" },
3
+ "trophy:basketball": { en: "Basketball trophy", ja: "バスケットボールのトロフィー" },
4
+ "trophy:football": { en: "Football trophy", ja: "アメリカンフットボールのトロフィー" },
5
+ "trophy:soccer-ball": { en: "Soccer ball trophy", ja: "サッカーボールのトロフィー" },
6
+ "trophy:tennis-cup": { en: "Two-handled cup with a pineapple", ja: "取っ手が二つあり、ふたにパイナップルの飾りが付いたカップ" },
7
+ "sport:ifaf": { en: "American football, international rules", ja: "国際ルールのアメリカンフットボール" },
8
+ "sport:pickleball": { en: "Pickleball paddle and ball", ja: "ピックルボールのパドルとボール" },
9
+ "sport:tabletennis": { en: "Table tennis paddle and ball", ja: "卓球のラケットとボール" },
10
+ "sport:squash": { en: "Squash racket and ball", ja: "スカッシュのラケットとボール" },
11
+ "sport:racquetball": { en: "Racquetball racket and ball", ja: "ラケットボールのラケットとボール" },
12
+ "sport:sepaktakraw": { en: "Woven ball", ja: "セパタクローの編み目のボール" },
13
+ "sport:teqball": { en: "Curved table and ball", ja: "テックボールの湾曲した台とボール" },
14
+ "sport:roundnet": { en: "Round net", ja: "ラウンドネットの円形ネット" },
15
+ "sport:netball": { en: "Ball and hoop", ja: "ネットボールのボールとゴールリング" },
16
+ "sport:artisticswimming": { en: "Raised legs", ja: "水面に上げた脚(アーティスティックスイミング)" },
17
+ "sport:afl": { en: "Oval ball", ja: "オーストラリアンフットボールのボール" },
18
+ "sport:gaelic": { en: "Round ball with seams", ja: "ゲーリックフットボールのボール" },
19
+ "sport:fieldhockey": { en: "Hooked stick and ball", ja: "フィールドホッケーのスティックとボール" },
20
+ "ball:basketball-6": { en: "Basketball, size 6", ja: "バスケットボール(6号球)" },
21
+ "ball:cricket-pink": { en: "Cricket ball, pink", ja: "クリケットボール(ピンク)" },
22
+ "ball:football": { en: "Football (NFL)", ja: "アメリカンフットボールのボール(NFL)" },
23
+ "ball:football-cfl": { en: "Football (CFL)", ja: "カナディアンフットボールのボール(CFL)" },
24
+ "ball:football-ifaf": { en: "Football (IFAF)", ja: "アメリカンフットボールのボール(IFAF)" },
25
+ "ball:afl": { en: "Australian football", ja: "オーストラリアンフットボールのボール" },
26
+ "ball:gaelic-football": { en: "Gaelic football", ja: "ゲーリックフットボールのボール" },
27
+ "ball:squash": { en: "Squash ball, double yellow dot", ja: "スカッシュボール(ダブルイエロードット)" },
28
+ "ball:squash-yellow": { en: "Squash ball, yellow dot", ja: "スカッシュボール(イエロードット)" },
29
+ "ball:squash-green": { en: "Squash ball, green dot", ja: "スカッシュボール(グリーンドット)" },
30
+ "ball:squash-red": { en: "Squash ball, red dot", ja: "スカッシュボール(レッドドット)" },
31
+ "ball:squash-blue": { en: "Squash ball, blue dot", ja: "スカッシュボール(ブルードット)" },
32
+ "ball:shuttlecock-feather": { en: "Shuttlecock, feather", ja: "シャトルコック(水鳥の羽根)" },
33
+ "ball:shuttlecock-nylon": { en: "Shuttlecock, nylon", ja: "シャトルコック(ナイロン)" },
34
+ "gear:hockey-stick": { en: "Hockey stick and puck", ja: "アイスホッケーのスティックとパック" },
35
+ "gear:goalie-stick": { en: "Ice hockey goalie stick", ja: "アイスホッケーのゴーリーのスティック" },
36
+ "gear:hockey-skate": { en: "Hockey skate", ja: "アイスホッケーのスケート靴" },
37
+ "gear:field-hockey-stick": { en: "Field hockey stick and ball", ja: "フィールドホッケーのスティックとボール" },
38
+ "gear:cricket-bat": { en: "Cricket bat and ball", ja: "クリケットのバットとボール" },
39
+ "gear:table-tennis-paddle": { en: "Table-tennis paddle and ball", ja: "卓球のラケットとボール" },
40
+ "gear:badminton-racket": { en: "Badminton racket and shuttlecock", ja: "バドミントンのラケットとシャトルコック" },
41
+ "gear:football-helmet": { en: "Football helmet", ja: "アメリカンフットボールのヘルメット" },
42
+ "gear:hurley": { en: "Hurley", ja: "ハーリー(ハーリングのスティック)" },
43
+ "trophy:sumo-cup": { en: "A tall silver cup on a tall stepped stand, with an ornate phoenix-crested handle on each side", ja: "段のある高い台に載った、背の高い銀の杯。両側の取っ手に鳳凰の飾りが付く" },
44
+ "trophy:championship-banner": { en: "A fringed banner on a pole with a gilt finial and an embroidered border, with no lettering unless some is given", ja: "金の先端飾りの付いた竿に掛けた、刺繍の縁と房の付いた旗。文字は指定したときだけ入る" },
45
+ "sport:sumo": { en: "Two wrestlers in the crouch they face each other in at the start of a bout, with their belts", ja: "仕切りの姿勢で向かい合う、廻しを締めた二人の力士" },
46
+ "sport:handball": { en: "A hand throwing the ball, with lines of speed", ja: "ボールを投げる手と、速さを表す線" },
47
+ "sport:kendo": { en: "The kendo helmet", ja: "剣道の面" },
48
+ "sport:judo": { en: "The judo suit and belt", ja: "柔道衣と帯" },
49
+ "sport:kyudo": { en: "A long bow, its string and an arrow", ja: "弦を張った長弓と矢" },
50
+ "sport:karate": { en: "A clenched fist", ja: "握りしめた拳" },
51
+ "gear:gunbai": { en: "The sumo referee's war fan, with its tassel", ja: "行司が持つ軍配と、その房" },
52
+ "gear:mawashi": { en: "The wrestler's belt, with the stiff cords that hang from its front", ja: "力士の廻しと、前に垂らした下がり" },
53
+ "gear:shinai": { en: "The kendo practice sword: four bamboo staves with a leather tip, a tie and a hilt", ja: "剣道の竹刀。四つ割りの竹に先革、中結、柄が付く" },
54
+ "gear:kendo-men": { en: "The kendo helmet: a steel grille, cloth flaps and a throat guard", ja: "剣道の面。面金、面布団、突き垂れが付く" },
55
+ "gear:judogi": { en: "The judo suit: a jacket with crossed lapels, trousers and a belt", ja: "柔道衣。上衣、ズボン、帯" },
56
+ "gear:obi": { en: "A tied belt in the colour of a rank, white to black", ja: "段級に応じた色の、結んだ帯(白から黒まで)" },
57
+ "gear:yumi": { en: "The long asymmetric bow, held a third of the way up, with its string and wrapped grip", ja: "上が長い非対称の長弓。弦を張り、握り革と籐巻きが付く" },
58
+ "gear:ya": { en: "A kyudo arrow with feather fletching, a nock and a steel point", ja: "弓道の矢。矢羽根、筈、矢尻が付く" },
59
+ "gear:karate-gi": { en: "The karate suit: a jacket with crossed lapels, trousers and a belt", ja: "空手衣。上衣、ズボン、帯" },
60
+ };