@johnmorrisdotca/dougu-sports 0.1.0 → 0.2.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 (192) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/NOTICE.md +9 -58
  3. package/README.md +174 -37
  4. package/dist/emblems/award/badge.d.ts +2 -2
  5. package/dist/emblems/award/badge.js +14 -5
  6. package/dist/emblems/award/crown.d.ts +1 -1
  7. package/dist/emblems/award/crown.js +14 -4
  8. package/dist/emblems/award/medal.d.ts +2 -2
  9. package/dist/emblems/award/medal.js +14 -5
  10. package/dist/emblems/award/shield.d.ts +1 -1
  11. package/dist/emblems/award/shield.js +10 -4
  12. package/dist/emblems/award/star.d.ts +1 -1
  13. package/dist/emblems/award/star.js +10 -4
  14. package/dist/emblems/ball/ball.afl.js +3 -2
  15. package/dist/emblems/ball/ball.basketball6.js +1 -1
  16. package/dist/emblems/ball/ball.core.d.ts +9 -3
  17. package/dist/emblems/ball/ball.core.js +13 -0
  18. package/dist/emblems/ball/ball.cricket.js +1 -1
  19. package/dist/emblems/ball/ball.curlingstone.d.ts +2 -0
  20. package/dist/emblems/ball/ball.curlingstone.js +11 -7
  21. package/dist/emblems/ball/ball.discus.js +1 -1
  22. package/dist/emblems/ball/ball.engine.js +3 -3
  23. package/dist/emblems/ball/ball.football.js +9 -7
  24. package/dist/emblems/ball/ball.gaelic.js +1 -1
  25. package/dist/emblems/ball/ball.object.d.ts +5 -2
  26. package/dist/emblems/ball/ball.object.js +3 -2
  27. package/dist/emblems/ball/ball.puck.d.ts +2 -0
  28. package/dist/emblems/ball/ball.puck.js +2 -2
  29. package/dist/emblems/ball/ball.rugby.js +3 -2
  30. package/dist/emblems/ball/ball.shuttlecock.d.ts +4 -0
  31. package/dist/emblems/ball/ball.shuttlecock.js +6 -5
  32. package/dist/emblems/ball/ball.squash.js +5 -5
  33. package/dist/emblems/emblem.api.d.ts +39 -1
  34. package/dist/emblems/emblem.api.js +20 -2
  35. package/dist/emblems/emblem.compose.d.ts +31 -0
  36. package/dist/emblems/emblem.compose.js +91 -0
  37. package/dist/emblems/emblem.core.d.ts +48 -2
  38. package/dist/emblems/emblem.core.js +30 -0
  39. package/dist/emblems/emblem.descriptions.d.ts +7 -0
  40. package/dist/emblems/emblem.descriptions.js +60 -0
  41. package/dist/emblems/emblem.display.d.ts +75 -0
  42. package/dist/emblems/emblem.display.js +214 -0
  43. package/dist/emblems/emblem.engrave.d.ts +50 -0
  44. package/dist/emblems/emblem.engrave.js +145 -0
  45. package/dist/emblems/emblem.equipment.d.ts +24 -0
  46. package/dist/emblems/emblem.equipment.js +57 -0
  47. package/dist/emblems/emblem.flip.d.ts +10 -0
  48. package/dist/emblems/emblem.flip.js +46 -0
  49. package/dist/emblems/emblem.ids.d.ts +19 -11
  50. package/dist/emblems/emblem.ids.js +21 -6
  51. package/dist/emblems/emblem.lathe.d.ts +3 -0
  52. package/dist/emblems/emblem.lathe.js +26 -4
  53. package/dist/emblems/emblem.medal.js +4 -4
  54. package/dist/emblems/emblem.pennant.d.ts +3 -0
  55. package/dist/emblems/emblem.pennant.js +79 -0
  56. package/dist/emblems/emblem.registry.js +20 -0
  57. package/dist/emblems/emblem.shapes.d.ts +19 -2
  58. package/dist/emblems/emblem.shapes.js +55 -13
  59. package/dist/emblems/emblem.sprite.d.ts +38 -0
  60. package/dist/emblems/emblem.sprite.js +65 -0
  61. package/dist/emblems/emblem.uri.d.ts +22 -0
  62. package/dist/emblems/emblem.uri.js +29 -0
  63. package/dist/emblems/gear/gear.badmintonracket.d.ts +1 -1
  64. package/dist/emblems/gear/gear.badmintonracket.js +18 -14
  65. package/dist/emblems/gear/gear.baseballglove.d.ts +1 -1
  66. package/dist/emblems/gear/gear.baseballglove.js +20 -14
  67. package/dist/emblems/gear/gear.budo.d.ts +17 -0
  68. package/dist/emblems/gear/gear.budo.js +60 -0
  69. package/dist/emblems/gear/gear.core.d.ts +12 -31
  70. package/dist/emblems/gear/gear.core.js +61 -54
  71. package/dist/emblems/gear/gear.cricketbat.d.ts +1 -1
  72. package/dist/emblems/gear/gear.cricketbat.js +16 -14
  73. package/dist/emblems/gear/gear.fieldhockeystick.d.ts +1 -1
  74. package/dist/emblems/gear/gear.fieldhockeystick.js +15 -14
  75. package/dist/emblems/gear/gear.footballhelmet.d.ts +1 -1
  76. package/dist/emblems/gear/gear.footballhelmet.js +15 -14
  77. package/dist/emblems/gear/gear.goaliemask.d.ts +1 -1
  78. package/dist/emblems/gear/gear.goaliemask.js +22 -16
  79. package/dist/emblems/gear/gear.goalnet.d.ts +1 -1
  80. package/dist/emblems/gear/gear.goalnet.js +24 -14
  81. package/dist/emblems/gear/gear.hockeystick.d.ts +1 -1
  82. package/dist/emblems/gear/gear.hockeystick.js +14 -14
  83. package/dist/emblems/gear/gear.index.js +5 -1
  84. package/dist/emblems/gear/gear.kendo.d.ts +2 -0
  85. package/dist/emblems/gear/gear.kendo.js +41 -0
  86. package/dist/emblems/gear/gear.kyudo.d.ts +2 -0
  87. package/dist/emblems/gear/gear.kyudo.js +31 -0
  88. package/dist/emblems/gear/gear.lacrossestick.d.ts +1 -1
  89. package/dist/emblems/gear/gear.lacrossestick.js +25 -14
  90. package/dist/emblems/gear/gear.skates.js +1 -1
  91. package/dist/emblems/gear/gear.sticks.js +2 -2
  92. package/dist/emblems/gear/gear.sumo.d.ts +2 -0
  93. package/dist/emblems/gear/gear.sumo.js +43 -0
  94. package/dist/emblems/gear/gear.tabletennispaddle.d.ts +1 -1
  95. package/dist/emblems/gear/gear.tabletennispaddle.js +15 -14
  96. package/dist/emblems/gear/gear.tennisracket.d.ts +1 -1
  97. package/dist/emblems/gear/gear.tennisracket.js +16 -14
  98. package/dist/emblems/pennant/championship.d.ts +2 -0
  99. package/dist/emblems/pennant/championship.js +4 -0
  100. package/dist/emblems/sport/afl.js +1 -1
  101. package/dist/emblems/sport/artisticswimming.js +1 -1
  102. package/dist/emblems/sport/cfl.d.ts +1 -1
  103. package/dist/emblems/sport/cfl.js +4 -4
  104. package/dist/emblems/sport/cricket.d.ts +1 -1
  105. package/dist/emblems/sport/cricket.js +13 -4
  106. package/dist/emblems/sport/fieldhockey.js +1 -1
  107. package/dist/emblems/sport/gaelic.js +1 -1
  108. package/dist/emblems/sport/handball.d.ts +1 -1
  109. package/dist/emblems/sport/handball.js +14 -4
  110. package/dist/emblems/sport/ifaf.d.ts +1 -1
  111. package/dist/emblems/sport/ifaf.js +4 -4
  112. package/dist/emblems/sport/judo.d.ts +2 -0
  113. package/dist/emblems/sport/judo.js +13 -0
  114. package/dist/emblems/sport/karate.d.ts +2 -0
  115. package/dist/emblems/sport/karate.js +13 -0
  116. package/dist/emblems/sport/kendo.d.ts +2 -0
  117. package/dist/emblems/sport/kendo.js +14 -0
  118. package/dist/emblems/sport/kyudo.d.ts +2 -0
  119. package/dist/emblems/sport/kyudo.js +15 -0
  120. package/dist/emblems/sport/mlb.d.ts +1 -1
  121. package/dist/emblems/sport/mlb.js +27 -4
  122. package/dist/emblems/sport/nba.d.ts +1 -1
  123. package/dist/emblems/sport/nba.js +11 -4
  124. package/dist/emblems/sport/netball.js +1 -1
  125. package/dist/emblems/sport/nfl.d.ts +2 -1
  126. package/dist/emblems/sport/nfl.js +14 -4
  127. package/dist/emblems/sport/nhl.d.ts +1 -1
  128. package/dist/emblems/sport/nhl.js +12 -4
  129. package/dist/emblems/sport/pickleball.js +1 -1
  130. package/dist/emblems/sport/racquetball.js +1 -1
  131. package/dist/emblems/sport/roundnet.js +1 -1
  132. package/dist/emblems/sport/rugby.d.ts +1 -1
  133. package/dist/emblems/sport/rugby.js +11 -4
  134. package/dist/emblems/sport/sepaktakraw.js +1 -1
  135. package/dist/emblems/sport/soccer.d.ts +1 -1
  136. package/dist/emblems/sport/soccer.js +30 -4
  137. package/dist/emblems/sport/squash.js +1 -1
  138. package/dist/emblems/sport/sumo.d.ts +2 -0
  139. package/dist/emblems/sport/sumo.js +15 -0
  140. package/dist/emblems/sport/tabletennis.js +1 -1
  141. package/dist/emblems/sport/tennis.d.ts +1 -1
  142. package/dist/emblems/sport/tennis.js +14 -4
  143. package/dist/emblems/sport/teqball.js +1 -1
  144. package/dist/emblems/sport/volleyball.d.ts +1 -1
  145. package/dist/emblems/sport/volleyball.js +24 -4
  146. package/dist/emblems/trophy/banner.d.ts +2 -0
  147. package/dist/emblems/trophy/banner.js +20 -0
  148. package/dist/emblems/trophy/baseball.js +1 -0
  149. package/dist/emblems/trophy/basketball.js +1 -0
  150. package/dist/emblems/trophy/belt.js +2 -1
  151. package/dist/emblems/trophy/bowl.js +1 -0
  152. package/dist/emblems/trophy/canadian-bowl.js +1 -0
  153. package/dist/emblems/trophy/championship-banner.d.ts +2 -0
  154. package/dist/emblems/trophy/championship-banner.js +67 -0
  155. package/dist/emblems/trophy/cricket-urn.js +1 -0
  156. package/dist/emblems/trophy/cup.d.ts +1 -1
  157. package/dist/emblems/trophy/cup.js +15 -4
  158. package/dist/emblems/trophy/football.js +2 -1
  159. package/dist/emblems/trophy/globe.js +1 -0
  160. package/dist/emblems/trophy/hockey-cup.js +2 -1
  161. package/dist/emblems/trophy/lidded-cup.js +1 -0
  162. package/dist/emblems/trophy/plaque.js +2 -1
  163. package/dist/emblems/trophy/ring.d.ts +2 -0
  164. package/dist/emblems/trophy/ring.js +30 -0
  165. package/dist/emblems/trophy/rugby-cup.js +1 -0
  166. package/dist/emblems/trophy/salver.js +1 -0
  167. package/dist/emblems/trophy/soccer-ball.js +2 -1
  168. package/dist/emblems/trophy/soccer-globe.js +1 -0
  169. package/dist/emblems/trophy/sumo-cup.d.ts +2 -0
  170. package/dist/emblems/trophy/sumo-cup.js +28 -0
  171. package/dist/emblems/trophy/tennis-cup.js +2 -1
  172. package/dist/emblems/trophy/tennis-plate.js +1 -0
  173. package/dist/emblems-entry.d.ts +15 -6
  174. package/dist/emblems-entry.js +7 -2
  175. package/dist/index.d.ts +17 -0
  176. package/dist/index.js +15 -0
  177. package/dist/turn-control.d.ts +101 -0
  178. package/dist/turn-control.js +363 -0
  179. package/dist/turn-entry.d.ts +2 -0
  180. package/dist/turn-entry.js +1 -0
  181. package/dist/version.d.ts +1 -1
  182. package/dist/version.js +1 -1
  183. package/package.json +7 -1
  184. package/LICENSES/Apache-2.0.txt +0 -202
  185. package/LICENSES/CC-BY-3.0.txt +0 -319
  186. package/LICENSES/upstream/game-icons.license.txt +0 -45
  187. package/LICENSES/upstream/noto-emoji-2D-svg.LICENSE +0 -13
  188. package/LICENSES/upstream/pictogrammers-mdi.LICENSE +0 -20
  189. package/dist/emblems/emblem.material.d.ts +0 -9
  190. package/dist/emblems/emblem.material.data.d.ts +0 -34
  191. package/dist/emblems/emblem.material.data.js +0 -85
  192. package/dist/emblems/emblem.material.js +0 -23
package/README.md CHANGED
@@ -11,7 +11,7 @@ Trophies, medals, crests, the icon of every sport, and the ball and gear of the
11
11
  <img alt="TypeScript" src="https://img.shields.io/badge/types-TypeScript-3178c6">
12
12
  </p>
13
13
 
14
- <p align="center"><a href="https://johnmorrisdotca.github.io/dougu-sports/"><strong>Open the demo →</strong></a> · <a href="https://johnmorrisdotca.github.io/dougu-sports/gallery.html">Gallery</a> · <a href="./docs/gallery.md">Every id</a> · <a href="./docs/turning.md">Turning</a> · <a href="./docs/layout.md">Layout</a></p>
14
+ <p align="center"><a href="https://johnmorrisdotca.github.io/dougu-sports/"><strong>Open the demo →</strong></a> · <a href="https://johnmorrisdotca.github.io/dougu-sports/gallery.html">Gallery</a> · <a href="./docs/gallery.md">Every id</a> · <a href="./docs/turning.md">Turning</a> · <a href="./docs/layout.md">Layout</a> · <a href="./docs/japanese-sports.md">Japanese sports</a></p>
15
15
 
16
16
  <p align="center">
17
17
  <picture>
@@ -31,7 +31,7 @@ Trophies, medals, crests, the icon of every sport, and the ball and gear of the
31
31
  </tr>
32
32
  </table>
33
33
 
34
- > **Status: preview.** 148 emblems: 20 trophies, 5 awards, 6 medals, 4 crests, a pictogram for each of the 33 sports, 47 balls and implements drawn in 3D, and 33 pieces of gear ([docs/layout.md](./docs/layout.md) says where each goes).
34
+ > **Status: preview.** 167 emblems: 24 trophies, 5 awards, 6 medals, 4 crests, a pictogram for each of the 38 sports, 47 balls and implements drawn in 3D, 42 pieces of gear (among them the Japanese sports and budo, [docs/japanese-sports.md](./docs/japanese-sports.md)) and a championship pennant; [docs/layout.md](./docs/layout.md) says where each goes. All of it is drawn for this package: no art is copied from another project.
35
35
 
36
36
  ## In 30 seconds
37
37
 
@@ -45,7 +45,7 @@ import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
45
45
  const svg = renderEmblem("trophy:hockey-cup", { size: 48 });
46
46
 
47
47
  console.log(svg.startsWith("<svg")); // true
48
- console.log(svg.includes("<title>Tall banded silver cup</title>")); // true
48
+ console.log(svg.includes("<title>Banded silver cup</title>")); // true
49
49
  ```
50
50
 
51
51
  Put the string in a page (`element.innerHTML = svg`), write it to a file, or send it from a server: it is plain SVG, with no script, no font and no network. The outline takes the page's text colour, so an emblem follows light and dark mode as the text does.
@@ -55,16 +55,20 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
55
55
  - **Sports sites** that mark a champion, a result or a list with a trophy, a medal or a crest, without licensing a logo.
56
56
  - **Scoreboards and brackets** that want a generic emblem for a team that has no logo, tinted in the team's colour.
57
57
  - **Anyone building a game or a card** who needs a ball or a piece of gear for a sport, in one style that matches the rest.
58
- - **Pages that care about weight**: one emblem is one module, 2 to 6 kB gzipped with the renderer for its kind (a medal about 3, a turning cup about 5), and the package says `"sideEffects": false`.
58
+ - **Pages that care about weight**: one emblem is one module, 2 to 7 kB gzipped with the renderer for its kind (a medal about 4.5, a turning cup about 7, an icon 2 to 3.6), and the package says `"sideEffects": false`.
59
59
 
60
60
  ## Features
61
61
 
62
62
  - **Three styles** for every emblem: `metal` (polished metal: a gradient, a highlight and a soft rim of reflected light, edged in a darker tone of its own metal, with no heavy outline), `line` (one clean outline in the page's text colour, made to read at 14 pixels) and `color` (flat fills); see [Theming](#theming).
63
63
  - **Size, tint, accent and theme** as options: a tint recolours the main part (a medal's metal, a crest's colour, a ball's patches), an accent the second colour (a ribbon, a crest's band, the pennants), a theme sets the ink for light, dark or either.
64
- - **Turning**: `emblemFrame` and `ballFrame` return the emblem at an angle, in plain SVG; see [docs/turning.md](./docs/turning.md).
64
+ - **Turning**: `emblemFrame` and `ballFrame` return the emblem at an angle, in plain SVG: every emblem turns, a ball rolls, a cup keeps its outline and moves its light, and everything flat (gear, a bat, a crown, a sport's icon) flips like a coin; `bindTurn` lets a drag, the arrow keys or an auto-turn do the turning in a page; see [docs/turning.md](./docs/turning.md).
65
+ - **Engraving**: text cut into a medal, a plaque, the belt, a ring, a banner, a pennant and the plinth of a cup, from `label`, `year` and `rank` or one `engrave` string, in the ink that reads at 4.5 to 1 on the metal, and it turns with the emblem; see [Engrave an emblem](#engrave-an-emblem).
66
+ - **Labels in two languages**: the `<title>` is English or Japanese (`locale`), your own words (`title: "…"`), or left out for an emblem that sits beside text that says the same (`title: false`).
67
+ - **As an image, a sprite, a podium or a case**: `emblemDataUri` for an `<img>`, a CSS background or a canvas, `emblemSprite` to draw one emblem fifty times cheaply, `sportEquipment` for what a sport is played with, and `podium` and `awardCase` for results and trophy shelves; see [docs/compose.md](./docs/compose.md).
65
68
  - **One module per item**, so a bundler takes only what is imported; see [Use it in your project](#use-it-in-your-project).
66
- - **Short names and helpers**: `"cup"` is `"trophy:cup"`, `"trophy:cup/line"` is the line style, and `crest`, `medal` and `sportIcon` draw a team's crest, a medal and a sport's icon.
67
- - **Typed ids**: `EmblemId` is a union of `award:*`, `trophy:*`, `medal:*`, `crest:*`, `ball:*`, `gear:*` and `sport:*` ids.
69
+ - **Short names and helpers**: `"cup"` is `"trophy:cup"`, `"trophy:cup/line"` is the line style, and `crest`, `medal`, `sportIcon` and `pennant` draw a team's crest, a medal, a sport's icon and a championship pennant.
70
+ - **Typed ids**: `EmblemId` is a union of `award:*`, `trophy:*`, `medal:*`, `crest:*`, `ball:*`, `gear:*`, `sport:*` and `pennant:*` ids.
71
+ - **Japanese sports and budō** (道具 is the name): a sumo cup, a championship banner, and the war fan, belt, bamboo sword, kendo helmet, judo and karate suits, rank belts, long bow and arrow, with Japanese names that are the governing bodies' words; see [docs/japanese-sports.md](./docs/japanese-sports.md).
68
72
  - **Generic by design**: no emblem carries a league's, a team's or a federation's name or mark.
69
73
  - **Accessible**: every drawing is `role="img"` with a `<title>`; see [Accessibility](#accessibility).
70
74
  - **Deterministic**: the same id and options give the same string; a gradient's id comes from its colour.
@@ -79,7 +83,7 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
79
83
  </tr>
80
84
  </table>
81
85
 
82
- Every emblem, with its id in both styles and a button that copies it, is on the [gallery page](https://johnmorrisdotca.github.io/dougu-sports/gallery.html); the same list as text, with its names, kind, source and the import that takes it alone, is [docs/gallery.md](./docs/gallery.md), made from the built package. [docs/emblems.md](./docs/emblems.md) says how the art is drawn.
86
+ Every emblem, with its id in both styles and a button that copies it, is on the [gallery page](https://johnmorrisdotca.github.io/dougu-sports/gallery.html); the same list as text, with its name, kind, source and description, is [docs/gallery.md](./docs/gallery.md) ([日本語](./docs/gallery.ja.md)), made from the built package. [docs/emblems.md](./docs/emblems.md) says how the art is drawn.
83
87
 
84
88
  ## Use it in your project
85
89
 
@@ -111,8 +115,8 @@ The alias is a name in your `package.json` only: the same package, the same code
111
115
  | --- | --- |
112
116
  | `@johnmorrisdotca/dougu-sports` | The full registry: every emblem by id, the functions, and each emblem as a constant |
113
117
  | `@johnmorrisdotca/dougu-sports/emblems` | `renderEmblem`, the ids and the types, with no single drawing imported by name |
114
- | `@johnmorrisdotca/dougu-sports/turn` | `emblemFrame` and `ballFrame` |
115
- | `@johnmorrisdotca/dougu-sports/<group>/<name>` | One emblem, alone: `trophy/hockey-cup`, `medal/gold`, `crest/shield`, `sport/nhl`, `award/crown`, `ball/soccer`, `gear/<name>` |
118
+ | `@johnmorrisdotca/dougu-sports/turn` | `emblemFrame`, `ballFrame` and `bindTurn` |
119
+ | `@johnmorrisdotca/dougu-sports/<group>/<name>` | One emblem, alone: `trophy/hockey-cup`, `medal/gold`, `crest/shield`, `sport/nhl`, `award/crown`, `ball/soccer`, `pennant/championship`, `gear/<name>` |
116
120
 
117
121
  ### One emblem and nothing else
118
122
 
@@ -123,7 +127,7 @@ console.log(TROPHY_HOCKEY_CUP.id); // trophy:hockey-cup
123
127
  console.log(TROPHY_HOCKEY_CUP.svg({ size: 24 }).includes('width="24"')); // true
124
128
  ```
125
129
 
126
- A bundler that imports this module takes the cup and the renderer for a body of revolution, and no other emblem: the package says `"sideEffects": false` and each constant is marked pure. `test/size.test.ts` bundles one item with esbuild and holds it to a limit for its kind (a ball 6.8 kB, a medal or a crest 3.6 kB, a cup 6.2 kB gzipped, most of that the renderer); `pnpm test:package` does the same from the packed tarball.
130
+ A bundler that imports this module takes the cup and the renderer for a body of revolution, and no other emblem: the package says `"sideEffects": false` and each constant is marked pure. `test/size.test.ts` bundles one item with esbuild and holds it to a limit for its kind (a ball 6.8 kB, a medal or a crest 4.6 kB, a cup 7.1 kB gzipped, most of that the renderer); `pnpm test:package` does the same from the packed tarball.
127
131
 
128
132
  ### In a page
129
133
 
@@ -220,6 +224,43 @@ console.log(ballFrame("ball:soccer", { yaw: 90 }) === ballFrame("ball:soccer", {
220
224
 
221
225
  More in [docs/turning.md](./docs/turning.md).
222
226
 
227
+ ### Engrave an emblem
228
+
229
+ ```js
230
+ import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
231
+
232
+ const medal = renderEmblem("medal:gold", { engrave: "MVP 2026" });
233
+ console.log(medal.includes(">MVP<") && medal.includes(">2026<")); // true
234
+ const plaque = renderEmblem("trophy:plaque", { label: "Champions", year: 2026 });
235
+ console.log(plaque.includes(">Champions<") && plaque.includes(">2026<")); // true
236
+ const cup = renderEmblem("trophy:hockey-cup", { engrave: "優勝 2026" });
237
+ console.log(cup.includes(">優<")); // true
238
+ console.log(renderEmblem("medal:gold").includes("<text")); // false
239
+ ```
240
+
241
+ A medal, a place badge, the plaque, the belt, a ring (the team up one shoulder and the year down the other), a banner and a pennant take an engraving, and so does the plinth of every cup that stands on one. Give one string (`engrave`, any text, Japanese included, up to three lines of 24 letters), or a `label`, a `year` and a `rank`: the rank is the biggest line, the year the smallest. The text is escaped, fitted to its face (a longer word is set smaller, and a space is a place to break the line when that makes bigger letters) and cut in the ink that reads at 4.5 to 1 on the metal, a tone of the metal, black or white, in the line style the page's ink.
242
+
243
+ ```js
244
+ import { emblemFrame } from "@johnmorrisdotca/dougu-sports/turn";
245
+
246
+ const at = (yaw) => emblemFrame("medal:gold", { engrave: "MVP", engraveBack: "2026", yaw });
247
+ console.log(at(0).includes(">MVP<"), at(180).includes(">MVP<"), at(180).includes(">2026<")); // true false true
248
+ ```
249
+
250
+ Turned, the engraving goes with its face: squeezed with a medal, hidden on its back (which has an engraving of its own when `engraveBack` is given), and on a cup set letter by letter round the plinth, so it foreshortens, slides behind the edge and comes round again. A drawn numeral or star that an engraving replaces is left out.
251
+
252
+ ### Draw a championship pennant
253
+
254
+ ```js
255
+ import { pennant } from "@johnmorrisdotca/dougu-sports/emblems";
256
+
257
+ const svg = pennant({ colors: ["#1f4e8c", "#f2c230"], text: "Champions", year: 2026 });
258
+ console.log(svg.includes(">CHAMPIONS<") && svg.includes(">2026<")); // true
259
+ console.log(pennant({ text: "Champions", view: "back" }).includes("CHAMPIONS")); // false
260
+ ```
261
+
262
+ A long triangle of felt on a dowel with a stitched edge, lettered with its words and its year as large as the triangle lets them be. The colours are the felt, the stitching and the lettering (which takes the stitching's colour unless a third is given); the back is plain felt with the dowel on the other side.
263
+
223
264
  ### Read what an emblem is
224
265
 
225
266
  ```js
@@ -235,9 +276,9 @@ console.log(emblemName("medal:gold", "ja")); // 金メダル
235
276
  ```js
236
277
  import { EMBLEM_GROUPS, EMBLEM_IDS, SPORT_NAMES } from "@johnmorrisdotca/dougu-sports";
237
278
 
238
- console.log(Object.keys(EMBLEM_GROUPS).join(" ")); // award trophy medal crest ball gear sport
279
+ console.log(Object.keys(EMBLEM_GROUPS).join(" ")); // award trophy medal crest ball gear sport pennant
239
280
  console.log(EMBLEM_IDS.includes("ball:soccer")); // true
240
- console.log(SPORT_NAMES.length); // 33
281
+ console.log(SPORT_NAMES.length); // 38
241
282
  ```
242
283
 
243
284
  ### Check a string from outside
@@ -250,6 +291,79 @@ console.log(parseEmblem("ball:soccer/line")?.style); // line
250
291
  console.log(parseEmblem("ball:nonesuch")); // undefined
251
292
  ```
252
293
 
294
+ ### Write the title in Japanese, in your own words, or not at all
295
+
296
+ ```js
297
+ import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
298
+
299
+ console.log(renderEmblem("medal:gold", { locale: "ja" }).includes("<title>金メダル</title>")); // true
300
+ console.log(renderEmblem("medal:gold", { title: "Champions <2026>" }).includes("<title>Champions &lt;2026&gt;</title>")); // true
301
+ console.log(renderEmblem("medal:gold", { title: false }).includes('aria-hidden="true"')); // true
302
+ ```
303
+
304
+ `locale` is `"en"` (the default) or `"ja"`. A `title` string is escaped and wins over the locale; `false` drops the `<title>` and marks the drawing `aria-hidden="true"`, for an emblem beside text that says the same.
305
+
306
+ ### Use an emblem as an image
307
+
308
+ ```js
309
+ import { emblemDataUri } from "@johnmorrisdotca/dougu-sports/emblems";
310
+
311
+ const src = emblemDataUri("sport:nhl", { size: 48, color: "#c8102e" });
312
+ console.log(src.startsWith("data:image/svg+xml;utf8,%3Csvg")); // true
313
+ console.log(decodeURIComponent(src).includes("currentColor")); // false
314
+ ```
315
+
316
+ `currentColor` does not cross an `<img>` boundary, so the ink is made a colour for you: `color` for the line, otherwise the theme's (`"dark"` is pale ink; `"light"` and the default are dark ink). Every character that could end an attribute or a CSS `url()` is percent-encoded, so the string goes in `img.src`, `background-image: url("…")` and `new Image()` for a canvas. More in [docs/compose.md](./docs/compose.md).
317
+
318
+ ### Draw one emblem many times
319
+
320
+ ```js
321
+ import { emblemSprite } from "@johnmorrisdotca/dougu-sports/emblems";
322
+
323
+ const sprite = emblemSprite(["ball:soccer", "medal:gold"]);
324
+ const cell = sprite.use("ball:soccer", { size: 24, title: false });
325
+ console.log(cell.startsWith('<svg width="24" height="24" aria-hidden="true"><use href="#')); // true
326
+ console.log(sprite.sheet.includes("<symbol")); // true
327
+ ```
328
+
329
+ Put `sprite.sheet` in the page once, then `sprite.use(id, { size, class, title })` for each cell. Sixty-four soccer balls are 2,304 nodes and 530 kB drawn inline and 228 nodes and 15 kB from a sheet; see [docs/compose.md](./docs/compose.md).
330
+
331
+ ### What a sport is played with
332
+
333
+ ```js
334
+ import { sportEquipment } from "@johnmorrisdotca/dougu-sports/emblems";
335
+
336
+ const nhl = sportEquipment("nhl");
337
+ console.log(nhl.ball, nhl.trophy); // ball:puck trophy:hockey-cup
338
+ console.log(nhl.gear.join(" ")); // gear:hockey-stick gear:hockey-skate gear:goalie-mask gear:goal-net
339
+ ```
340
+
341
+ Each of the 38 sports has a trophy, most have a ball and gear, and a sport in the Games has a medal; every id is one `renderEmblem` draws.
342
+
343
+ ### A podium and an award case
344
+
345
+ ```js
346
+ import { awardCase, podium } from "@johnmorrisdotca/dougu-sports/emblems";
347
+
348
+ const svg = podium([{ name: "Aoki", label: "9.80 s" }, { name: "Dupont" }, { name: "Rossi" }]);
349
+ console.log(svg.includes("<desc>1st: Aoki (9.80 s); 2nd: Dupont; 3rd: Rossi</desc>")); // true
350
+ const shelf = awardCase([{ emblem: "trophy:hockey-cup", count: 3 }, { emblem: "medal:gold" }]);
351
+ console.log(shelf.includes("×3")); // true
352
+ ```
353
+
354
+ Both are one SVG string in the page's text colour, with a title and a description. A podium takes a flag as SVG markup or a URL, drawn as an image so that it cannot run anything; see [docs/compose.md](./docs/compose.md).
355
+
356
+ ### Let a drag, the keys or a clock turn it
357
+
358
+ ```js no-run
359
+ import { bindTurn } from "@johnmorrisdotca/dougu-sports/turn";
360
+
361
+ const turner = bindTurn(document.getElementById("cup"), "trophy:tennis-cup", { size: 160, speed: 36 });
362
+ document.getElementById("spin").onclick = () => turner.togglePlay();
363
+ ```
364
+
365
+ A drag turns it, the arrow keys turn it, Space starts and stops an auto-turn, and nothing moves until you ask; see [docs/turning.md](./docs/turning.md).
366
+
253
367
  ### In React, Vue and the rest
254
368
 
255
369
  The functions return strings, so a framework puts them where it puts any markup: `dangerouslySetInnerHTML={{ __html: renderEmblem("medal:gold") }}` in React, `v-html` in Vue, `{@html …}` in Svelte. The string holds no script and no external reference.
@@ -265,24 +379,25 @@ An emblem is a small object: `id`, `en` and `ja` names, a `source` (who drew it)
265
379
  | Kind | What it is | A turn |
266
380
  | --- | --- | --- |
267
381
  | `lathe` | A body of revolution: a cup, a bowl, an urn, a column with a ball or a globe on it, a stand with flat faces | Keeps its outline, and moves its light, its handles, its seams and its grooves |
268
- | `flat` | A front and a back drawn from shapes: a medal, a crest, a plaque, a rosette | Flips like a coin, thick at the rim as it goes edge on |
382
+ | `flat` | A front and a back drawn from shapes: a medal, a crest, a plaque, a rosette, a ring, a banner, a pennant | Flips like a coin, thick at the rim as it goes edge on |
269
383
  | `ball` | A ball or an implement drawn in true 3D, with its panels, seams and marks on the surface | Rolls |
270
- | `icon` | One drawing: a Material Symbols icon or a sport's pictogram | Is not turned |
271
- | `gear` | A piece of equipment, a flat drawing | Is not turned |
384
+ | `icon` | One drawing: an award, a plain cup or a sport's pictogram | Flips like a coin: its front, its back mirrored and a little darker, and a thin rim |
385
+ | `gear` | A piece of equipment, a flat drawing in layers | Flips like a coin, as an icon does |
272
386
 
273
387
  ### The groups
274
388
 
275
389
  | Group | What it holds | Folder |
276
390
  | --- | --- | --- |
277
- | `award` | Five awards from Material Symbols: a medal, a badge, a crown, a star, a shield | `src/emblems/award/` |
278
- | `trophy` | Twenty trophies: ten that stand for a league's cup in a generic form (a tall banded cup, a ring of pennants round a baseball, a football on a stand, a ball over a net, a wide two-handled bowl, a globe held up by spiral figures, a gilt dish, a lidded cup with a pineapple, an urn, a gilded cup), plain cups, bowls and dishes, a plaque, a belt, a wreath, a rosette | `src/emblems/trophy/` |
391
+ | `award` | Five awards: a medal, a badge, a crown, a star, a shield | `src/emblems/award/` |
392
+ | `trophy` | Twenty-four trophies: ten that stand for a league's cup in a generic form (a tall banded cup, a ring of pennants round a baseball, a football on a stand, a ball over a net, a wide two-handled bowl, a globe held up by spiral figures, a gilt dish, a lidded cup with a pineapple, an urn, a gilded cup), plain cups, bowls and dishes, a plaque, a belt, a wreath, a rosette, a championship ring, a rafter banner, a phoenix-handled sumo cup and a championship banner | `src/emblems/trophy/` |
279
393
  | `medal` | Gold, silver and bronze medals on a ribbon of five stripes, and a badge for each of the first three places | `src/emblems/medal/` |
280
394
  | `crest` | Four generic crests, tinted by a team's colours, with its letters | `src/emblems/crest/` |
281
395
  | `ball` | 47 balls and implements, in 3D, each with its official size: soccer, basketball, baseball, tennis, rugby, the footballs, golf, the puck, the curling stone and the rest | `src/emblems/ball/` |
282
- | `gear` | 33 pieces of equipment: sticks, rackets, skates, a glove, a helmet, nets and posts, a javelin, starting blocks | `src/emblems/gear/` |
283
- | `sport` | One pictogram for each of the thirty-three sports | `src/emblems/sport/` |
396
+ | `gear` | 42 pieces of equipment: sticks, rackets, skates, a glove, a helmet, nets and posts, a javelin, starting blocks, and for the Japanese sports a war fan, a sumo belt, a bamboo sword, a kendo helmet, a judo suit, a belt, a long bow, an arrow and a karate suit | `src/emblems/gear/` |
397
+ | `sport` | One pictogram for each of the thirty-eight sports | `src/emblems/sport/` |
398
+ | `pennant` | A felt championship pennant on a dowel, with a stitched edge, lettered with its words and its year | `src/emblems/pennant/` |
284
399
 
285
- The thirty-three sports the ball, gear and sport emblems are made for are `SPORT_NAMES`: NFL, CFL, IFAF, NHL, NBA, MLB, soccer, curling, tennis, volleyball, badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, swimming, water polo, diving, artistic swimming, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey, handball, athletics and skating. How the trophies are drawn, and what each stands for, is in [docs/emblems.md](./docs/emblems.md); the balls and the gear are described in [src/emblems/README.md](./src/emblems/README.md).
400
+ The thirty-eight sports the ball, gear and sport emblems are made for are `SPORT_NAMES` (the five Japanese ones, sumo, kendo, judo, kyudo and karate, have a pictogram and their gear, and no ball): NFL, CFL, IFAF, NHL, NBA, MLB, soccer, curling, tennis, volleyball, badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, swimming, water polo, diving, artistic swimming, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey, handball, athletics and skating. How the trophies are drawn, and what each stands for, is in [docs/emblems.md](./docs/emblems.md); the balls and the gear are described in [src/emblems/README.md](./src/emblems/README.md).
286
401
 
287
402
  ## API
288
403
 
@@ -291,22 +406,32 @@ The thirty-three sports the ball, gear and sport emblems are made for are `SPORT
291
406
  | `renderEmblem(ref, options?)` | An emblem as SVG. `ref` is an id, an id with a style (`"medal:gold/line"`), or an emblem |
292
407
  | `emblemSvg` | The same as `renderEmblem` |
293
408
  | `crest(options?)` | A crest by shape, colours and letters |
409
+ | `pennant(options?)` | A championship pennant by colours, words and year |
294
410
  | `medal(kind, options?)` | A gold, silver or bronze medal on its ribbon |
295
411
  | `sportIcon(sport, options?)` | The pictogram of a sport, by the names of `SPORT_NAMES`; an unknown sport is an error |
296
412
  | `lineup(ids, options?)` | Several balls side by side, at their true relative sizes (or all as large as the largest) |
297
413
  | `emblemFrame(ref, options?)` | An emblem turned by `yaw` and `pitch` degrees (and `roll` for a ball) |
414
+ | `bindTurn(element, ref, options?)` | Draws an emblem into an element and lets a drag, the arrow keys, Space or a clock turn it; returns a controller with `angles`, `playing`, `turnable`, `setAngles`, `update`, `play`, `pause`, `togglePlay` and `destroy` |
415
+ | `emblemDataUri(ref, options?)` | An emblem as a `data:image/svg+xml;utf8,…` address for an `<img>`, a CSS background or a canvas, with the ink made a colour (`color`, or the theme's) |
416
+ | `emblemSprite(ids, options?)` | A hidden sheet of `<symbol>`s with unique ids, and `use(id, { size, class, title })` for the markup of each use |
417
+ | `sportEquipment(sport)` | The ball, gear, trophy and medal of a sport, as ids of the registry |
418
+ | `podium(places, options?)` | First, second and third on tiered steps, with medals or trophies, names, flags and lines of text, as one SVG |
419
+ | `awardCase(items, options?)` | A team's trophies on a shelf or in a row, with `×N` count badges, wrapping into rows, as one SVG |
298
420
  | `ballFrame(id, options?)` | A ball rolled; an id that is not a ball is an error |
299
421
  | `parseEmblem(value)` | The id and style a string names, or `undefined` |
300
422
  | `isEmblemId(value)`, `isBallId(value)` | Whether a value is the id of an emblem, or of a ball |
301
423
  | `emblemOf(ref)` | The emblem object a reference names |
302
- | `emblemInfo(id)`, `emblemName(id, language?)`, `emblemModel(id)` | What an emblem is: its names, kind and source, and the data it is drawn from |
424
+ | `emblemInfo(id)`, `emblemName(id, language?)`, `emblemModel(id)` | What an emblem is: its short names (which are its accessible names), kind and source, a longer `description` where it has one, and the data it is drawn from |
303
425
  | `EMBLEMS` | Every emblem as markup in the metal style at 64 pixels, by id |
304
426
  | `EMBLEM_TABLE` | Every emblem object, by id |
305
- | `TROPHY_HOCKEY_CUP`, `MEDAL_GOLD`, `CREST_SHIELD`, `SPORT_NHL`, `BALL_SOCCER`, `GEAR_HURLEY`... | Each emblem as a constant, named by its id in capitals (`trophy:hockey-cup`); [docs/gallery.md](./docs/gallery.md) lists every constant with its id and the module that takes it alone |
427
+ | `TROPHY_HOCKEY_CUP`, `MEDAL_GOLD`, `CREST_SHIELD`, `SPORT_NHL`, `BALL_SOCCER`, `GEAR_HURLEY`... | Each emblem as a constant, named by its id in capitals (`trophy:hockey-cup`); [docs/gallery.md](./docs/gallery.md) ([日本語](./docs/gallery.ja.md)) lists every emblem and states the rule for its constant and the module that takes it alone |
306
428
  | `EMBLEM_IDS`, `EMBLEM_GROUPS`, `EMBLEM_FOLDERS`, `EMBLEM_ALIASES` | Every id, the groups, the folder of each group's art, and the short names (`cup` for `trophy:cup`) |
307
- | `AWARD_IDS`, `TROPHY_IDS`, `MEDAL_IDS`, `CREST_IDS`, `BALL_IDS`, `GEAR_IDS`, `SPORT_IDS` | The ids of each group |
429
+ | `AWARD_IDS`, `TROPHY_IDS`, `MEDAL_IDS`, `CREST_IDS`, `BALL_IDS`, `GEAR_IDS`, `SPORT_IDS`, `PENNANT_IDS` | The ids of each group |
308
430
  | `MEDAL_KINDS`, `CREST_SHAPES` | The kinds of medal, and the shapes of crest |
309
- | `SPORT_NAMES` | The thirty-three sports |
431
+ | `SPORT_NAMES` | The thirty-eight sports |
432
+ | `JAPANESE_IDS` | The ids of the Japanese sports and budo, together: sumo, kendo, judo, kyudo and karate, with their trophies and gear ([docs/japanese-sports.md](./docs/japanese-sports.md)) |
433
+ | `OBI_RANKS`, `obi(rank, options?)` | The colours of a belt from `white` to `black`, and the belt of a rank drawn |
434
+ | `EMBLEM_DESCRIPTIONS` | The longer description of an emblem, in English and Japanese; `emblemInfo(id).description` is the one of an id |
310
435
  | `EMBLEM_STYLES`, `EMBLEM_INK`, `EMBLEM_PAGE`, `METALS` | The styles, the ink and page colours the themes use, and the metals |
311
436
  | `VERSION` | The package's version |
312
437
 
@@ -318,12 +443,21 @@ The thirty-three sports the ball, gear and sport emblems are made for are `SPORT
318
443
  | `size` | A number of pixels, 4096 at most | `64` |
319
444
  | `tint` | `#rgb`, `#rrggbb` or `rgb(r, g, b)` | the emblem's own colour |
320
445
  | `accent` | `#rgb`, `#rrggbb` or `rgb(r, g, b)` | the emblem's second colour (a ribbon, a band, pennants) |
321
- | `initials` | Up to three letters (a crest only) | none: the crest has a star |
446
+ | `initials` | Up to three letters (a crest, or the championship banner) | none: the crest has a star, the banner a ring and a star |
322
447
  | `theme` | `"inherit"`, `"auto"`, `"light"`, `"dark"` | `"inherit"` |
323
448
  | `grain` | `true` or `false` (a ball only) | on for a ball of 48 pixels or more that is not turning |
449
+ | `engrave` | Any text, up to three lines of 24 letters, Japanese included: cut into the face (see [Engrave an emblem](#engrave-an-emblem)) | none |
450
+ | `label`, `year`, `rank` | The words, the year (smaller, under them) and the number (the biggest line) to engrave when `engrave` is not given | none (a place badge's rank is its place) |
451
+ | `engraveBack` | The text of a medal's, ring's or banner's back, shown when it is turned over | a plain back |
452
+ | `numberColor` | The colour of a pennant's lettering | the stitching's colour |
453
+ | `view` | `"front"` or `"back"`: which side of a pennant is drawn at rest | `"front"` |
454
+ | `locale` | `"en"`, `"ja"`: the language of the `<title>` | `"en"` |
455
+ | `title` | A string (written, escaped, as the `<title>`) or `false` (no `<title>`, and `aria-hidden="true"`) | the emblem's name |
324
456
  | `yaw`, `pitch`, `roll` (turning only; `roll` for a ball) | Degrees from the resting view | `0` |
325
457
 
326
- The types are `EmblemId`, `EmblemRef`, `EmblemOptions`, `FrameOptions`, `EmblemStyle`, `EmblemTheme`, `Emblem`, `EmblemInfo`, `EmblemKind`, `EmblemSource`, `EmblemGroup`, `CrestOptions`, `CrestShape`, `MedalKind`, `LineupOptions`, `PieceSize`, `SportName`, the id types of each group, and the types of the models the emblems are drawn from (`LatheModel`, `FlatModel`, `MaterialModel` and their parts).
458
+ `podium` and `awardCase` take their own options too (`width`, `style`, `theme`, `locale`, `title`, `desc`, and for the case `perRow`, `size` and `layout`), and `emblemDataUri`, `emblemSprite` and `bindTurn` theirs: see [docs/compose.md](./docs/compose.md) and [docs/turning.md](./docs/turning.md).
459
+
460
+ The types are `EmblemId`, `EmblemRef`, `EmblemOptions`, `EmblemLocale`, `FrameOptions`, `DataUriOptions`, `Sprite`, `SpriteOptions`, `UseOptions`, `SportEquipment`, `PodiumPlace`, `PodiumOptions`, `AwardItem`, `AwardCaseOptions`, `DisplayOptions`, `TurnControlOptions`, `TurnController`, `TurnAngles`, `TurnContainer`, `TurnEvent`, `EmblemStyle`, `EmblemTheme`, `Emblem`, `EmblemInfo`, `EmblemKind`, `EmblemSource`, `EmblemGroup`, `CrestOptions`, `CrestShape`, `PennantOptions`, `PennantId`, `MedalKind`, `LineupOptions`, `PieceSize`, `EmblemDescription`, `ObiRank`, `SportName`, the id types of each group (and `JapaneseId`), and the types of the models the emblems are drawn from (`LatheModel`, `FlatModel` and their parts).
327
461
 
328
462
  ## Theming
329
463
 
@@ -340,17 +474,19 @@ The metals are `METALS` (gold `#d9a620`, silver `#aeb6c0`, bronze `#b8733a`); ea
340
474
 
341
475
  ## Limits
342
476
 
343
- - A turn is drawn in plain SVG, not in 3D: a cup keeps its silhouette and moves its light, handles and seams; a medal is squeezed; a ball is projected from its own geometry, panel by panel, and has no grain while it turns. Gear and pictograms are not turned.
477
+ - A turn is drawn in plain SVG, not in 3D: a cup keeps its silhouette and moves its light, handles and seams; a medal is squeezed; a ball is projected from its own geometry, panel by panel, and has no grain while it turns. Gear, icons and pictograms flip like a coin, with the back as a mirror of the front and a thin rim; a pennant's back is its own drawing; one turn (`src/emblems/emblem.flip.ts`) does it for all of them.
344
478
  - A tint is one colour, the main one, and an accent a second. The pieces of a trophy that are another metal (the gilt of a plate, the green bands of a globe, the black foot of a cup) keep their own colour.
345
479
  - The trophies are generic: each is drawn for this package in a simplified form that a reader knows at a glance, and none is traced from a photograph or carries a name, a mark or an engraving.
346
- - A trophy in the metal style is about 3 to 4.5 kB of markup, a medal or a crest about 1 to 2 kB, a line drawing about 1 to 2.5 kB; a ball in 3D is 5 to 13 kB, and some gear is as large, because it is copied from detailed artwork.
480
+ - A trophy in the metal style is about 3 to 4.5 kB of markup, a medal or a crest about 1 to 2 kB, a line drawing about 1 to 2.5 kB; a ball in 3D is 5 to 13 kB, and a piece of gear is 1 to 4 kB, drawn in layers.
347
481
  - The size is a number of pixels up to 4096; the drawing is a vector at any size.
348
482
  - No emblem carries a real league's, team's or federation's mark.
349
483
 
350
484
  ## Accessibility
351
485
 
352
486
  - Every emblem is `role="img"` with a `<title>` that names it in English ("Gold medal", "Soccer ball"). `emblemName(id, "ja")` gives the Japanese name for a caller that writes its own label.
353
- - Where an emblem is only decoration next to text that says the same, hide it from a screen reader with `aria-hidden="true"` on the element that holds it.
487
+ - Where an emblem is only decoration next to text that says the same, pass `title: false`: the drawing has no `<title>` and is `aria-hidden="true"`. `locale: "ja"` writes the Japanese name, with `lang="ja"` on the drawing.
488
+ - A podium and an award case are `role="img"` with a `<title>` and a `<desc>` that says who stands where, or what is in the case, with the counts; the emblems inside carry no titles of their own, so nothing is read twice.
489
+ - `bindTurn` gives its element a tab stop, a role description and a description that names the arrow keys and Space, and `touch-action: none` so that a drag turns the emblem instead of scrolling. Nothing turns until the reader asks, and under `prefers-reduced-motion` an auto-turn only starts when the caller forces it.
354
490
  - Colour is never the only carrier of meaning: the `line` style has no colour at all.
355
491
  - The ink reads at 4.5 to 1 against the page the `light` and `dark` themes name, and a crest's letters read at 4.5 to 1 on the crest's colour, whatever the colour; the tests hold both.
356
492
  - Nothing moves by itself: turning happens when the caller asks for a frame, and the demo's sliders are 44 pixels tall.
@@ -361,7 +497,7 @@ Any current browser, and Node 22 or later. The package is plain strings, so it a
361
497
 
362
498
  ## Languages
363
499
 
364
- The package's own words are the emblems' names, in English (`en`) and Japanese (`ja`), read with `emblemName(id, language)`. The `<title>` inside a drawing is English. The demo's header and footer come in English and Japanese.
500
+ The package's own words are the emblems' names, in English (`en`) and Japanese (`ja`), read with `emblemName(id, language)`. The `<title>` inside a drawing is English unless you pass `locale: "ja"` or a `title` of your own; a podium's and an award case's default title and description, and `bindTurn`'s description for a screen reader, come in both languages the same way. The demo's header and footer come in English and Japanese.
365
501
 
366
502
  ## Roadmap
367
503
 
@@ -370,7 +506,7 @@ The package's own words are the emblems' names, in English (`en`) and Japanese (
370
506
 
371
507
  ## Architecture
372
508
 
373
- The code is `src/emblems/`: the core (options, colours, gradients, the wrapper), the id lists, the registry, the renderers (the body of revolution, the flat object and icon, the Material icon, and the ball and gear engines) and one module per emblem, or per family of balls and gear, in a folder for its group; [docs/layout.md](./docs/layout.md) has the folders and how to add one. The package has no state and no clock: every function is a pure function of its arguments.
509
+ The code is `src/emblems/`: the core (options, colours, gradients, the wrapper), the id lists, the registry, the renderers (the body of revolution, the flat object and icon, and the ball and gear engines) and one module per emblem, or per family of balls and gear, in a folder for its group; [docs/layout.md](./docs/layout.md) has the folders and how to add one. The package has no state and no clock: every function is a pure function of its arguments.
374
510
 
375
511
  ## The name
376
512
 
@@ -378,7 +514,7 @@ Dougu (道具, *dōgu*, どうぐ) is Japanese for a tool or a piece of equipmen
378
514
 
379
515
  ## Where it comes from, and where it is used
380
516
 
381
- The emblems are drawn for this package or made from the open sources listed in [NOTICE.md](./NOTICE.md), each with its licence in [LICENSES/](./LICENSES/): sixteen icons are Material Symbols (Apache 2.0), fetched at a pinned commit by `scripts/fetch-material-symbols.mjs`; some gear is copied from Noto Emoji, Wikimedia Commons and game-icons.net, with its credit; everything else is drawn here, and the rulebooks the balls' sizes were read from are in [docs/references.md](./docs/references.md). It is made for [spxn.com](https://spxn.com), the historical record of the NHL, NBA, MLB, NFL and CFL, and for the other packages of the family that draw sport.
517
+ Every emblem is drawn for this package, and nothing is copied from another project: no icon set, no emoji and no clip art ([NOTICE.md](./NOTICE.md) says so, and keeps the rulebooks the balls' sizes were read from, listed in [docs/references.md](./docs/references.md)). It is made for [spxn.com](https://spxn.com), the historical record of the NHL, NBA, MLB, NFL and CFL, and for the other packages of the family that draw sport.
382
518
 
383
519
  ### Used by
384
520
 
@@ -387,7 +523,7 @@ The emblems are drawn for this package or made from the open sources listed in [
387
523
  ### The family
388
524
 
389
525
  <!-- family:start (made by scripts/family-readme.mjs from scripts/family-template.mjs; change those, not this) -->
390
- Dougu Sports is one of twenty-seven packages, each made for the same site, each at
526
+ Dougu Sports is one of twenty-eight packages, each made for the same site, each at
391
527
  [github.com/johnmorrisdotca](https://github.com/johnmorrisdotca). The code of every one is MIT.
392
528
 
393
529
  - [Korokoro](https://github.com/johnmorrisdotca/korokoro) (コロコロ): dice, with notation, exact odds, real sounds and the dice of many games. [Demo](https://johnmorrisdotca.github.io/korokoro/).
@@ -417,8 +553,9 @@ Dougu Sports is one of twenty-seven packages, each made for the same site, each
417
553
  - [Kyogijo Stadiums](https://github.com/johnmorrisdotca/kyogijo-stadiums) (競技場): sports fields, rinks, courts and ballparks drawn to scale as SVG, with each team and the score on them. [Demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/).
418
554
  - [Taisen Brackets](https://github.com/johnmorrisdotca/taisen-brackets) (対戦): a sport-agnostic tournament bracket, drawn as SVG, from a list of ties. [Demo](https://johnmorrisdotca.github.io/taisen-brackets/).
419
555
  - [Dougu Sports](https://github.com/johnmorrisdotca/dougu-sports) (道具): sports emblems as SVG: trophies, medals, crests, and the ball and gear of every sport, with optional 3D turning. [Demo](https://johnmorrisdotca.github.io/dougu-sports/).
556
+ - [Senshu Jerseys](https://github.com/johnmorrisdotca/senshu-jerseys) (選手): sports jerseys, sweaters, kits, caps, helmets and retired-number banners as SVG, front and back, with optional 2.5D turning. [Demo](https://johnmorrisdotca.github.io/senshu-jerseys/).
420
557
 
421
- **This package is Dougu Sports.** The demos of all twenty-seven share one header and footer, so each links the rest.
558
+ **This package is Dougu Sports.** The demos of all twenty-eight share one header and footer, so each links the rest.
422
559
  <!-- family:end -->
423
560
 
424
561
  ## Development
@@ -428,7 +565,7 @@ pnpm install
428
565
  pnpm check # lint, types, tests, the build and the packed package
429
566
  pnpm dev # the demo on http://127.0.0.1:7200/
430
567
  pnpm test:demo # the demo in a real browser
431
- pnpm test:readme # the README's and the docs' examples, and docs/gallery.md
568
+ pnpm test:readme # the README's and the docs' examples, and docs/gallery.md and docs/gallery.ja.md
432
569
  pnpm screenshots # retake the README's pictures
433
570
  ```
434
571
 
@@ -440,7 +577,7 @@ Bug reports and ideas go in the [issues](https://github.com/johnmorrisdotca/doug
440
577
 
441
578
  ## Changes
442
579
 
443
- See [CHANGELOG.md](./CHANGELOG.md). 0.1.0 brings the full set of 148 emblems; 0.0.1 was the first preview.
580
+ See [CHANGELOG.md](./CHANGELOG.md). 0.2.1 draws every ball and implement to the rulebook's proportions; 0.2.0 is 167 emblems, every one drawn here, with the Japanese sports, engraving, a turn for every emblem and the compose helpers; 0.1.0 brought the first full set of 148; 0.0.1 was the first preview.
444
581
 
445
582
  ## Credits
446
583
 
@@ -1,2 +1,2 @@
1
- /** Award badge. */
2
- export declare const AWARD_BADGE: import("../emblem.core.ts").Emblem<import("../emblem.material.ts").MaterialModel>;
1
+ /** Badge with a star. */
2
+ export declare const AWARD_BADGE: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -1,5 +1,14 @@
1
- // Award badge: the Material Symbols icon `workspace_premium` (Google, Apache License 2.0; see NOTICE.md), in metal, line and flat colour.
2
- import { M_WORKSPACE_PREMIUM } from "../emblem.material.data.js";
3
- import { defineMaterial } from "../emblem.material.js";
4
- /** Award badge. */
5
- export const AWARD_BADGE = /* @__PURE__ */ defineMaterial("award:badge", "Award badge", "表彰バッジ", M_WORKSPACE_PREMIUM, "gold");
1
+ // Badge: a seal with a star and two tails of ribbon, drawn for this package, in metal, line and flat colour.
2
+ import { circlePath, defineIcon, starPath } from "../emblem.shapes.js";
3
+ /** Badge with a star. */
4
+ export const AWARD_BADGE = /* @__PURE__ */ defineIcon("award:badge", "Badge", "バッジ", "ours", {
5
+ metal: "gold",
6
+ ribbon: "#c0392b",
7
+ front: [
8
+ ["r", "M21 41L12 61l10-4.4 5.4 6.4 4.4-17zM43 41l9 20-10-4.4-5.4 6.4-4.4-17z"],
9
+ ["o", starPath(32, 26, 24, 21, 18)],
10
+ ["e", circlePath(32, 26, 16.6), "2"],
11
+ ["m", starPath(32, 26, 10.6, 4.6)],
12
+ ["l", "M17 18a17 17 0 0 1 11-9 20 20 0 0 0-11 19z"],
13
+ ],
14
+ });
@@ -1,2 +1,2 @@
1
1
  /** Crown. */
2
- export declare const AWARD_CROWN: import("../emblem.core.ts").Emblem<import("../emblem.material.ts").MaterialModel>;
2
+ export declare const AWARD_CROWN: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -1,5 +1,15 @@
1
- // Crown: the Material Symbols icon `crown` (Google, Apache License 2.0; see NOTICE.md), in metal, line and flat colour.
2
- import { M_CROWN } from "../emblem.material.data.js";
3
- import { defineMaterial } from "../emblem.material.js";
1
+ // Crown: three points tipped with balls over a jewelled band, drawn for this package, in metal, line and flat colour.
2
+ import { circlePath, defineIcon } from "../emblem.shapes.js";
4
3
  /** Crown. */
5
- export const AWARD_CROWN = /* @__PURE__ */ defineMaterial("award:crown", "Crown", "王冠", M_CROWN, "gold");
4
+ export const AWARD_CROWN = /* @__PURE__ */ defineIcon("award:crown", "Crown", "王冠", "ours", {
5
+ metal: "gold",
6
+ ribbon: "#c0392b",
7
+ front: [
8
+ ["m", "M8 48L5 19L20 31L32 11L44 31L59 19L56 48z"],
9
+ ["e", "M12.4 43.4L10.6 28.6L21 37L32 19.6L43 37L53.4 28.6L51.6 43.4", "1.6"],
10
+ ["o", `${circlePath(5, 17, 3.6)}${circlePath(32, 9, 3.8)}${circlePath(59, 17, 3.6)}`],
11
+ ["m", "M8 50h48v8H8z"],
12
+ ["r", `${circlePath(18, 54, 2.2)}${circlePath(32, 54, 2.2)}${circlePath(46, 54, 2.2)}`],
13
+ ["l", "M12 24l6.4 5.2-1.6 12L13.6 41z"],
14
+ ],
15
+ });
@@ -1,2 +1,2 @@
1
- /** Medal. */
2
- export declare const AWARD_MEDAL: import("../emblem.core.ts").Emblem<import("../emblem.material.ts").MaterialModel>;
1
+ /** Medal on a ribbon. */
2
+ export declare const AWARD_MEDAL: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -1,5 +1,14 @@
1
- // Medal: the Material Symbols icon `military_tech` (Google, Apache License 2.0; see NOTICE.md), in metal, line and flat colour.
2
- import { M_MILITARY_TECH } from "../emblem.material.data.js";
3
- import { defineMaterial } from "../emblem.material.js";
4
- /** Medal. */
5
- export const AWARD_MEDAL = /* @__PURE__ */ defineMaterial("award:medal", "Medal", "メダル", M_MILITARY_TECH, "gold");
1
+ // Medal: a ribbon with a notched end and a star hanging from it, drawn for this package, in metal, line and flat colour.
2
+ import { defineIcon, starPath } from "../emblem.shapes.js";
3
+ /** Medal on a ribbon. */
4
+ export const AWARD_MEDAL = /* @__PURE__ */ defineIcon("award:medal", "Medal", "メダル", "ours", {
5
+ metal: "gold",
6
+ ribbon: "#c0392b",
7
+ front: [
8
+ ["r", "M21 3h22v26L32 23.4 21 29z"],
9
+ ["e", "M26 3v22M38 3v22", "1.4"],
10
+ ["m", "M32 27.4a2.6 2.6 0 1 1 0 5.2a2.6 2.6 0 1 1 0-5.2z"],
11
+ ["m", starPath(32, 46, 16.4, 7)],
12
+ ["l", "M32 34.6l3.4 8-9.4 1.4z"],
13
+ ],
14
+ });
@@ -1,2 +1,2 @@
1
1
  /** Shield. */
2
- export declare const AWARD_SHIELD: import("../emblem.core.ts").Emblem<import("../emblem.material.ts").MaterialModel>;
2
+ export declare const AWARD_SHIELD: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -1,5 +1,11 @@
1
- // Shield: the Material Symbols icon `shield` (Google, Apache License 2.0; see NOTICE.md), in metal, line and flat colour.
2
- import { M_SHIELD } from "../emblem.material.data.js";
3
- import { defineMaterial } from "../emblem.material.js";
1
+ // Shield: a shield with a bevelled face, drawn for this package, in metal, line and flat colour.
2
+ import { defineIcon } from "../emblem.shapes.js";
4
3
  /** Shield. */
5
- export const AWARD_SHIELD = /* @__PURE__ */ defineMaterial("award:shield", "Shield", "盾", M_SHIELD, "silver");
4
+ export const AWARD_SHIELD = /* @__PURE__ */ defineIcon("award:shield", "Shield", "盾", "ours", {
5
+ metal: "silver",
6
+ front: [
7
+ ["m", "M32 4L10 12v18c0 14 9 25 22 30 13-5 22-16 22-30V12z"],
8
+ ["e", "M32 10.4L15.6 16.4V30c0 10.6 6.4 18.8 16.4 22.8 10-4 16.4-12.2 16.4-22.8V16.4z", "2"],
9
+ ["l", "M17 18l13-5v38C21 46 17 38 17 30z"],
10
+ ],
11
+ });
@@ -1,2 +1,2 @@
1
1
  /** Star. */
2
- export declare const AWARD_STAR: import("../emblem.core.ts").Emblem<import("../emblem.material.ts").MaterialModel>;
2
+ export declare const AWARD_STAR: import("../emblem.core.ts").Emblem<import("../emblem.shapes.ts").FlatModel>;
@@ -1,5 +1,11 @@
1
- // Star: the Material Symbols icon `star` (Google, Apache License 2.0; see NOTICE.md), in metal, line and flat colour.
2
- import { M_STAR } from "../emblem.material.data.js";
3
- import { defineMaterial } from "../emblem.material.js";
1
+ // Star: a five-pointed star with a bevelled face, drawn for this package, in metal, line and flat colour.
2
+ import { defineIcon, starPath } from "../emblem.shapes.js";
4
3
  /** Star. */
5
- export const AWARD_STAR = /* @__PURE__ */ defineMaterial("award:star", "Star", "星", M_STAR, "gold");
4
+ export const AWARD_STAR = /* @__PURE__ */ defineIcon("award:star", "Star", "星", "ours", {
5
+ metal: "gold",
6
+ front: [
7
+ ["m", starPath(32, 34, 29, 12.4)],
8
+ ["e", starPath(32, 35, 18.6, 7.8), "1.8"],
9
+ ["l", "M32 8.4l5 14.6-5 3.6-5-3.6z"],
10
+ ],
11
+ });
@@ -6,10 +6,11 @@ import { mix } from "./ball.core.js";
6
6
  export const BALL_AFL = /* @__PURE__ */ defineBall({
7
7
  id: "ball:afl",
8
8
  en: "Australian football",
9
- ja: "オーストラリアンフットボールのボール",
9
+ ja: "オージーボール",
10
10
  size: { extentMm: 280, lengthMm: 280, circumferenceMm: 550.0, longCircumferenceMm: 725.0, rule: "Laws of Australian Football 2026, Law 4 The Football, 4.1 Specifications", note: "The Laws give the two circumferences (720-730 mm and 545-555 mm) and no length: 280 mm is the length of an ellipse of those two girths." },
11
11
  spec: {
12
- axes: [1, 0.7, 0.7],
12
+ // An ellipsoid of the Laws' two girths: 550 mm round the middle makes it 175 mm across, 280 mm long.
13
+ axes: [1, 0.6253, 0.6253],
13
14
  view: { yaw: -30, pitch: 20, roll: -25 },
14
15
  base: "#b4202b",
15
16
  mat: { gloss: 0.55, shade: "#2a0408", grain: { f: 1.0, a: 0.34 } },
@@ -4,7 +4,7 @@ import { basketballSpec } from "./ball.basketball.js";
4
4
  export const BALL_BASKETBALL_6 = /* @__PURE__ */ defineBall({
5
5
  id: "ball:basketball-6",
6
6
  en: "Basketball, size 6",
7
- ja: "バスケットボール(6号球)",
7
+ ja: "バスケットボール6号球",
8
8
  size: { extentMm: 230.0, diameterMm: 230.0, circumferenceMm: 722.5, massG: [510, 550], rule: "FIBA Basketball Equipment 2026, Rule 2 Basketballs, 2.4 and Table 1 (size 6 = women's competitions)", note: "Diameter worked out from the middle of the circumference range." },
9
9
  spec: basketballSpec("#e57a26"),
10
10
  });