@johnmorrisdotca/taisen-brackets 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/NOTICE.md +4 -0
- package/README.md +198 -27
- package/dist/background.d.ts +19 -0
- package/dist/background.js +66 -0
- package/dist/backgrounds-entry.d.ts +2 -0
- package/dist/backgrounds-entry.js +1 -0
- package/dist/family-backgrounds.d.ts +61 -0
- package/dist/family-backgrounds.js +453 -0
- package/dist/furniture.d.ts +10 -0
- package/dist/furniture.js +29 -0
- package/dist/groups.d.ts +50 -0
- package/dist/groups.js +204 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +5 -2
- package/dist/layout.js +56 -6
- package/dist/layouts.d.ts +48 -0
- package/dist/layouts.js +388 -0
- package/dist/locales.js +10 -0
- package/dist/marks.d.ts +4 -0
- package/dist/marks.js +32 -2
- package/dist/matchup.js +2 -0
- package/dist/playin.d.ts +8 -0
- package/dist/playin.js +232 -0
- package/dist/render.d.ts +8 -1
- package/dist/render.js +492 -79
- package/dist/road.draw.js +6 -3
- package/dist/road.js +1 -1
- package/dist/road.types.d.ts +1 -1
- package/dist/seeding.js +4 -2
- package/dist/table.js +6 -3
- package/dist/text.d.ts +1 -1
- package/dist/text.js +4 -4
- package/dist/theme.d.ts +13 -1
- package/dist/theme.js +29 -8
- package/dist/types.d.ts +116 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,58 @@ All notable changes to this project are written here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.6.0] - 2026-10-14
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`layout`**: the same ties drawn eight ways. `"tree"` (the default) is the bracket as ever, drawn exactly as before; the rest take the tree's places, lines and round names or plan their own, and all work with `background`, both looks, the four sizes, the five languages, `href` links, seeds, codes, `flags` and `flagHref`, marks and tiles. [docs/layouts.md](docs/layouts.md).
|
|
14
|
+
- **`rows`**: each team a row, its name left and its mark right, a seed tag at the outer corner and a result slot (empty until played) at the end facing the centre.
|
|
15
|
+
- **`shields`**: marks in shield shapes with "vs" between, the matchups on both sides of the trophy, no lines.
|
|
16
|
+
- **`update`**: a compact score-update card: abbreviation, seed and series score a side, the rounds to come empty.
|
|
17
|
+
- **`columns`**: tall slots that grow toward the centre, the two halves in two colours (`--tb-conf-a`, `--tb-conf-b`, `CONFERENCE_COLORS`), "VS" tags, big seed numbers, the final as two tall slots. `at: true` writes "AT" in place of "VS" (a word in each language), the home side drawn second; `Matchup.home` names it.
|
|
18
|
+
- **`playin`**: the NBA's play-in: tiles for the seeds that need no game, the games in columns, a solid arrow for a winner and a dashed one for a loser, "Winner 9/10" and "Loser 7/8" until they are played, the seeds earned at the end.
|
|
19
|
+
- **`series`**: a tall card (1080 by 1350 unless a `size` is asked for) of one line a series, "BOS 4–0 MIA", the winner bold, the east above the west with the final between.
|
|
20
|
+
- **`groups`**: one card a group, a title tile and a row a team with its mark, name and record or points, the places that go through marked (`qualify`). `standings: "points"` (played, won, drawn, lost, goal difference, points) or `"record"` (won, lost, softball's). New `groupStandings(input)` (the tables as data) and `groupsTable(input)` (as HTML).
|
|
21
|
+
- A box too small for everything leaves out the seed tag, then the length of the names, then the score's slot; a geometry test over every layout, size and look holds that nothing sticks out.
|
|
22
|
+
- **Loser edges**: a `feeds` entry can be `{ tie, result: "winner" | "loser" }` (a string is still a winner), `Tie.from` says where each side comes from (`Source = { tie, result }`), and `Matchup.stage: "play-in"` keeps a game out of the tree (`layout.playIn`, `Tie.playIn`). A bracket with none of it is drawn exactly as before. A circle of feeds, or a tie that feeds itself, throws an error naming the ties. `advanceWinners` fills a side from a loser, `bracketTable` calls the games "Play-in" and says "Loser of A v B".
|
|
23
|
+
- **`headers: true`**: a big title tile over each half (West and East, AFC and NFC) in the colour of that half, in any layout.
|
|
24
|
+
- **A lone final is centred.** A tournament whose tree is a final alone with a third-place match (the World Cups of 1974 and 1978) is drawn with the final centred, the champion over it and the third place under it, in every layout, size and look, not off to one side.
|
|
25
|
+
- **One stylesheet for several drawings**: `styleScope` (a class that carries the rules in place of the drawing's own), `style: false` (leave the `<style>` out of a second drawing) and `bracketStyle(options)` (the rules, for a page that writes them once). The ids of the drawings stay apart.
|
|
26
|
+
- New words in the five languages: `vs`, `at`, `groupName`, `colPlayed` to `colPoints`, `playIn`, `playInWinner`, `playInLoser`, `seedSlot`, `winnerOf`, `loserOf`. The French and Japanese were read by native-language reviewers; the Spanish and German need one (docs/languages.md).
|
|
27
|
+
- The demo has a layout switcher on each sport (NHL rows and update, NFL columns, NBA play-in and series, World Cup shields, made-up groups, softball groups), "Headers" and "AT" chips, and a gallery of the layouts on their backgrounds. New demo data: the 2024 NBA play-in (typed from English Wikipedia, CC BY-SA 4.0) and two made-up group stages.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- The README's pictures are **WebP**, made in the browser by `pnpm images` (no tool beyond Chromium), two to three times smaller than the JPEG they replaced at no visible loss; the repository's `docs/images` shrinks with them.
|
|
32
|
+
- The README, docs/roadmap.md and docs/references.md say what 0.6.0 built and what is left.
|
|
33
|
+
|
|
34
|
+
## [0.5.0] - 2026-10-14
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **`background`**: a poster background under a bracket or a road chart. A preset's name draws one of **twenty-five**, each drawn in code (gradients, radial glows, patterns, bezier bands, markings) in a dark and a light variant, deterministic and at most 6 kB: `midnight`, `crimson`, `royal`, `emerald`, `pitch`, `ice`, `hardwood`, `infield`, `turf`, `ball-panels`, `swirl`, `waves`, `glow`, `floodlights`, `confetti`, `carbon`, `aurora`, `sunburst`, `chevrons`, `halftone`, `argyle`, `contour`, `stardust`, `mesh` and `spotlight`. Five read as the sport's playing surface: soccer's mowing stripes and markings, hockey's scratched ice with its centre circle, lines and faceoff spots, basketball's planks and court, baseball's grass, dirt and base paths, football's turf, yard lines and end zones. The text, lines, boxes, marks and accent take the colours that read over each (4.5 to 1 against the background's dominant colours, a test over every preset, both variants and every size, and over colours of your own, with a veil where a mid-tone ground needs one). With `theme: "auto"` both variants are drawn and the stylesheet shows the one that fits the page. [docs/backgrounds.md](docs/backgrounds.md).
|
|
39
|
+
- **`background: { preset, colors, angle, intensity, seed, theme }`** tunes a preset, and **`background: { image, fit, dim, theme }`** draws a picture of your own as an `<image>` under a veil (`cover` or `contain`, 0 to 1 deep); the address must be http(s), relative or `data:image/…` (anything else throws), and is escaped. An unknown preset or a bad value throws a `RangeError` that names it. `roadToFinal` takes the same option. The default, the look's plain colour, is drawn exactly as before.
|
|
40
|
+
- **`src/family-backgrounds.ts`**, the drawing of the twenty-five as one dependency-free file that other packages of the family copy byte for byte: `backgroundSvg(preset, { width, height, theme, colors, angle, intensity, seed, id }) => { defs, body, ink }`, `BACKGROUND_PRESETS`, `contrastRatio`, `FAMILY_BACKGROUNDS_VERSION`. Its sha256 and version are held by `test/family-backgrounds.test.ts`; it is also the `/backgrounds` entry point. The copy rule is in docs/backgrounds.md.
|
|
41
|
+
- **Seed tags**: `seeds: true` in the road look writes a small tag (`C1`, `WC2`, `P3`) beside each mark, from the new `Matchup.seeds`, else the new `Team.tag`, else the number `Team.seed`; in a box of marks alone it sits above the mark.
|
|
42
|
+
- **`codes`** and **`vs`** for a bracket's road look: a team's three letters under its mark, and a "v" between the two marks of a box of marks alone.
|
|
43
|
+
- **A team with no flag or logo is a tile** in the road look: a rounded square with its abbreviation, filled with the team's `color` (white or near-black letters, whichever reads) or neutral.
|
|
44
|
+
- **`flagHref(code)`**: a flag as an address to load, for pages that cannot afford an inline flag of 80 kB twice; tried where `flags` gives none, written once as a symbol. **Every `mark` address** is now written once as a symbol and used wherever the team appears, instead of a long `<image href>` per use.
|
|
45
|
+
- **`tieClass(tie)`**: a class word for a tie's group, so that a page's own style can highlight or dim ties (a division); only words of letters, digits, `-` and `_` are kept.
|
|
46
|
+
- The demo has a background picker (all twenty-five as swatches, your own colours, an image read in the browser and never uploaded), a gallery of the twenty-five on the sports they suit, and opens every example on the background of its sport. NHL 2024 carries its seed tags.
|
|
47
|
+
- `pnpm images` redoes every picture of `docs/images` in one command, the two grids of the twenty-five included; `pnpm test:readme` checks that every picture the README and the docs name exists. [docs/roadmap.md](docs/roadmap.md) and [docs/references.md](docs/references.md): what is planned (new layouts and a group-stage table for 0.6.0) and the pictures that prompted it, as mood only.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- **Marks, text and round names stuck out of their boxes**, in every size and both looks: in a tall bracket's boxes of marks the score under the marks was not counted when the marks were sized, so the flags crossed the box's top and bottom (Croatia and Japan in the round of 16 on a phone); a shoot-out's score ("1 (3)") crowded the next team's, and now sits beside the score where it fits the column, or under it. A box of marks is laid out as a stack (tag, mark, letters, score, shoot-out) and the marks are made as large as the whole stack allows. Bold text was measured as regular; it is now measured bold, so a name no longer runs under a score or the word "bye".
|
|
52
|
+
- **The names of the rounds met the connector lines.** In a tall bracket the lines now turn at the edge of the box they leave and the names stand on their own strip between the rounds, each moved along it to a place the lines do not cross, set a little smaller and on a snugger pill where the room is tight. (On a phone a round of eight or more boxes across leaves no room: the name then stands over the lines on its own pill.)
|
|
53
|
+
- **Round names were cut with an ellipsis** in a wide column ("Conference Quarterfi…"): a name is set smaller, down to 8, and then on two lines, on a taller pill (road) or two lines of text (classic), and the strip over the boxes grows to hold them. A name is cut only as a last resort.
|
|
54
|
+
- `test/geometry.test.ts` measures every drawing's marks, text, pills and lines from the markup and asserts all of this for every example, size and look.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- The demo's default view is the road look on the background that suits each sport. A bracket's classic look is unchanged apart from the fixes above.
|
|
59
|
+
- The README's pictures are regenerated (JPEG, to keep the repository small) with the new backgrounds and the fixed boxes.
|
|
60
|
+
|
|
9
61
|
## [0.4.0] - 2026-10-14
|
|
10
62
|
|
|
11
63
|
### Added
|
package/NOTICE.md
CHANGED
|
@@ -9,6 +9,8 @@ The code of this package is under the MIT licence (see [LICENSE](LICENSE)). The
|
|
|
9
9
|
| The demo's World Cup results of 2026 (`demo/data/worldcup-2026.js`) | openfootball/worldcup, https://github.com/openfootball/worldcup, read through spxn.com | CC0 |
|
|
10
10
|
| The demo's NHL results (`demo/data/nhl-2024.js`, `demo/data/nhl-1984.js`) | Every game of the 2024 and the 1984 Stanley Cup playoffs and each team's conference, from the NHL ("NHL", as spxn.com credits it), read through spxn.com | Facts; credited to the NHL |
|
|
11
11
|
| The demo's NBA results (`demo/data/nba-2024.js`) | Every game of the 2024 NBA playoffs and each team's conference, from English Wikipedia (https://en.wikipedia.org/wiki/2024_NBA_playoffs), read through spxn.com, which holds them as sourced from Wikipedia | **CC BY-SA 4.0** (https://creativecommons.org/licenses/by-sa/4.0/legalcode). That file is an adaptation and is shared under the same licence, with this credit; the pictures of the NBA bracket carry it too |
|
|
12
|
+
| The demo's NBA play-in results (`demo/data/nba-2024-playin.js`) | The six games of the 2024 NBA play-in tournament and the seeds of the teams that played in it, typed from English Wikipedia's article on the 2023-24 NBA season (https://en.wikipedia.org/wiki/2023%E2%80%9324_NBA_season#Play-in_tournament), read on 2026-10-14; not read through spxn.com | **CC BY-SA 4.0** (https://creativecommons.org/licenses/by-sa/4.0/legalcode). That file is an adaptation and is shared under the same licence, with this credit; the pictures of the play-in carry it too |
|
|
13
|
+
| The demo's group tables (`cupGroups`, `softballGroups` in `demo/data.js`) | Made up: the clubs and teams do not exist, and the results come from a fixed recipe in the file | Nothing to credit; MIT with the rest |
|
|
12
14
|
| The demo's MLS results (`demo/data/mls-2024.js`) | Every match of the 2024 MLS Cup Playoffs and each club's conference, read through spxn.com, whose MLS data is from openfootball/world (CC0, https://github.com/openfootball/world) checked against English Wikipedia (https://en.wikipedia.org/wiki/2024_MLS_Cup_Playoffs) | **CC BY-SA 4.0** (Wikipedia is in the mix, so the file is an adaptation shared under the same licence, with this credit); openfootball's part is CC0; the pictures of the MLS bracket carry the same licence |
|
|
13
15
|
| The demo's NFL results (`demo/data/nfl-2024.js`) | Every game of the playoffs of the 2024 NFL season (January and February 2025) and each team's conference, from nflverse (https://github.com/nflverse/nflverse-data), read through spxn.com | CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/), credited to nflverse |
|
|
14
16
|
| The demo's CFL results (`demo/data/cfl-2024.js`) | Every game of the 2024 CFL playoffs and each team's division, from English Wikipedia (https://en.wikipedia.org/wiki/2024_CFL_season), read through spxn.com | **CC BY-SA 4.0**, as for the NBA file above; the pictures of the CFL bracket carry it too |
|
|
@@ -25,3 +27,5 @@ The code of this package is under the MIT licence (see [LICENSE](LICENSE)). The
|
|
|
25
27
|
The flags in the demo are for the nations of the World Cups of 2022 and 2026: `AR AT AU BA BE BR CA CD CH CI CO CV DE DZ EC EG ES FR GB-ENG GH HR JP KR MA MX NL NO PL PT PY SE SN US ZA`. The package itself ships no flag, no logo and no data of the leagues.
|
|
26
28
|
|
|
27
29
|
No code, text or picture was taken from the bracket libraries compared in [docs/compare.md](docs/compare.md); that page records what each says of itself.
|
|
30
|
+
|
|
31
|
+
**Backgrounds.** The twenty-five backgrounds (`src/family-backgrounds.ts`) are drawn in code from gradients, patterns and paths and are original work, MIT-licensed with the package; none is traced from, or copies, anyone's artwork, logo, trophy or photograph, and no image file is used. The pictures of other brackets that inspired the design are listed, as mood only, in docs/references.md; nothing of them is in the package. The NHL 2024 seed tags in the demo (C1, WC2, P3, A1, M2 and so on) are the divisional places and wild cards of that season's playoff field, as the league names them.
|
package/README.md
CHANGED
|
@@ -11,22 +11,22 @@ Give it the games, series, two-legged ties or replays of a tournament and it wor
|
|
|
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/taisen-brackets/"><strong>Open the demo →</strong></a> · <a href="./docs/layout.md">Layout</a> · <a href="./docs/drawing.md">Drawing</a> · <a href="./docs/road.md">Road to the final</a> · <a href="./docs/formats.md">Formats</a> · <a href="./docs/compare.md">How it compares</a></p>
|
|
14
|
+
<p align="center"><a href="https://johnmorrisdotca.github.io/taisen-brackets/"><strong>Open the demo →</strong></a> · <a href="./docs/layout.md">Layout</a> · <a href="./docs/layouts.md">Layouts</a> · <a href="./docs/drawing.md">Drawing</a> · <a href="./docs/road.md">Road to the final</a> · <a href="./docs/backgrounds.md">Backgrounds</a> · <a href="./docs/formats.md">Formats</a> · <a href="./docs/compare.md">How it compares</a></p>
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
17
17
|
<picture>
|
|
18
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-dark.
|
|
19
|
-
<img alt="The 2022 World Cup knockout: two halves of eight teams meeting at the final in the centre, with Argentina's round flag and the word Champion above it and the third-place match below. Each box has both teams' round flags, abbreviations and scores, with penalties in brackets." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.
|
|
18
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-dark.webp">
|
|
19
|
+
<img alt="The 2022 World Cup knockout: two halves of eight teams meeting at the final in the centre, with Argentina's round flag and the word Champion above it and the third-place match below. Each box has both teams' round flags, abbreviations and scores, with penalties in brackets." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.webp" width="720">
|
|
20
20
|
</picture>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
<table align="center">
|
|
24
24
|
<tr>
|
|
25
25
|
<td align="center" valign="top">
|
|
26
|
-
<img alt="The poster look: the 2026 World Cup knockout of 32 nations as round flags on dark navy joined by gold lines, Spain's flag in the centre above the word Champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk.
|
|
26
|
+
<img alt="The poster look: the 2026 World Cup knockout of 32 nations as round flags on dark navy joined by gold lines, Spain's flag in the centre above the word Champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk.webp" width="470"><br><em>The poster look: flags only, gold on navy (the 2026 World Cup).</em>
|
|
27
27
|
</td>
|
|
28
28
|
<td align="center" valign="top">
|
|
29
|
-
<img alt="The 2022 World Cup on a phone: the champion at the top, then the rounds as rows, the first round at the top and at the bottom, the final in the middle, and the third-place match at the foot." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/phone-light.
|
|
29
|
+
<img alt="The 2022 World Cup on a phone: the champion at the top, then the rounds as rows, the first round at the top and at the bottom, the final in the middle, and the third-place match at the foot." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/phone-light.webp" width="190"><br><em>On a phone the rounds are rows.</em>
|
|
30
30
|
</td>
|
|
31
31
|
</tr>
|
|
32
32
|
</table>
|
|
@@ -37,22 +37,22 @@ One layout draws them all, each from real results: the demo has a picker for the
|
|
|
37
37
|
|
|
38
38
|
<table>
|
|
39
39
|
<tr>
|
|
40
|
-
<td align="center" valign="top"><img alt="The 2024 NHL playoffs: Western and Eastern conferences, best-of-seven series, Florida Panthers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl-desk-light.
|
|
41
|
-
<td align="center" valign="top"><img alt="The 1984 Stanley Cup playoffs: the Campbell and Wales conferences, a best-of-five first round, Edmonton Oilers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl1984-desk-light.
|
|
42
|
-
<td align="center" valign="top"><img alt="The 2024 NBA playoffs: sixteen teams in two conferences, Boston Celtics as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nba-desk-light.
|
|
40
|
+
<td align="center" valign="top"><img alt="The 2024 NHL playoffs: Western and Eastern conferences, best-of-seven series, Florida Panthers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl-desk-light.webp" width="360"><br><em>NHL 2024, series</em></td>
|
|
41
|
+
<td align="center" valign="top"><img alt="The 1984 Stanley Cup playoffs: the Campbell and Wales conferences, a best-of-five first round, Edmonton Oilers as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nhl1984-desk-light.webp" width="360"><br><em>NHL 1984, an older era</em></td>
|
|
42
|
+
<td align="center" valign="top"><img alt="The 2024 NBA playoffs: sixteen teams in two conferences, Boston Celtics as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nba-desk-light.webp" width="360"><br><em>NBA 2024</em></td>
|
|
43
43
|
</tr>
|
|
44
44
|
<tr>
|
|
45
|
-
<td align="center" valign="top"><img alt="The 2022 MLB postseason: byes for the top two seeds of each league, Houston Astros as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/byes-desk-light.
|
|
46
|
-
<td align="center" valign="top"><img alt="The playoffs of the 2024 NFL season: single games, byes for the top seed of each conference, the Super Bowl at the centre, Philadelphia Eagles as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nfl-desk-light.
|
|
47
|
-
<td align="center" valign="top"><img alt="The 2024 CFL playoffs: division semi-finals and finals, byes, the Grey Cup at the centre, Toronto Argonauts as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/cfl-desk-light.
|
|
45
|
+
<td align="center" valign="top"><img alt="The 2022 MLB postseason: byes for the top two seeds of each league, Houston Astros as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/byes-desk-light.webp" width="360"><br><em>MLB 2022, byes</em></td>
|
|
46
|
+
<td align="center" valign="top"><img alt="The playoffs of the 2024 NFL season: single games, byes for the top seed of each conference, the Super Bowl at the centre, Philadelphia Eagles as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/nfl-desk-light.webp" width="360"><br><em>NFL 2024 season, the Super Bowl</em></td>
|
|
47
|
+
<td align="center" valign="top"><img alt="The 2024 CFL playoffs: division semi-finals and finals, byes, the Grey Cup at the centre, Toronto Argonauts as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/cfl-desk-light.webp" width="360"><br><em>CFL 2024, the Grey Cup</em></td>
|
|
48
48
|
</tr>
|
|
49
49
|
<tr>
|
|
50
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup knockout stage." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.
|
|
51
|
-
<td align="center" valign="top"><img alt="The 1938 World Cup: replays." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/replays-desk-light.
|
|
52
|
-
<td align="center" valign="top"><img alt="The 2026 World Cup as a flags-only poster, in Japanese." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk-ja.
|
|
50
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup knockout stage." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/hero-desk-light.webp" width="360"><br><em>World Cup 2022</em></td>
|
|
51
|
+
<td align="center" valign="top"><img alt="The 1938 World Cup: replays." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/replays-desk-light.webp" width="360"><br><em>World Cup 1938, replays</em></td>
|
|
52
|
+
<td align="center" valign="top"><img alt="The 2026 World Cup as a flags-only poster, in Japanese." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/poster-desk-ja.webp" width="360"><br><em>World Cup 2026 poster, in Japanese</em></td>
|
|
53
53
|
</tr>
|
|
54
54
|
<tr>
|
|
55
|
-
<td align="center" valign="top"><img alt="The 2024 MLS Cup Playoffs: a wild card match, a best-of-three round one, then single matches to the MLS Cup, LA Galaxy as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/mls-desk-light.
|
|
55
|
+
<td align="center" valign="top"><img alt="The 2024 MLS Cup Playoffs: a wild card match, a best-of-three round one, then single matches to the MLS Cup, LA Galaxy as champion." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/mls-desk-light.webp" width="360"><br><em>MLS 2024, best of three</em></td>
|
|
56
56
|
<td></td>
|
|
57
57
|
<td></td>
|
|
58
58
|
</tr>
|
|
@@ -64,17 +64,180 @@ One layout draws them all, each from real results: the demo has a picker for the
|
|
|
64
64
|
|
|
65
65
|
<table>
|
|
66
66
|
<tr>
|
|
67
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look, wide: large round flags, big bold scores, the loser quiet, the rounds on pills, and Argentina's path to the final as a dotted line." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/path-desk-light.
|
|
68
|
-
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look on a card, 1080 by 1350: the champion at the top, then the rounds as rows." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/card-light.
|
|
69
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a phone in the dark: Argentina and France as large flags, and each one's matches with the score between the two flags." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-phone-dark.
|
|
67
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look, wide: large round flags, big bold scores, the loser quiet, the rounds on pills, and Argentina's path to the final as a dotted line." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/path-desk-light.webp" width="460"><br><em>The road look, wide, with Argentina's path.</em></td>
|
|
68
|
+
<td align="center" valign="top"><img alt="The 2022 World Cup in the road look on a card, 1080 by 1350: the champion at the top, then the rounds as rows." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/card-light.webp" width="260"><br><em>A card, 1080 by 1350.</em></td>
|
|
69
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a phone in the dark: Argentina and France as large flags, and each one's matches with the score between the two flags." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-phone-dark.webp" width="190"><br><em>The road to the final, on a phone.</em></td>
|
|
70
70
|
</tr>
|
|
71
71
|
<tr>
|
|
72
|
-
<td align="center" valign="top"><img alt="The same bracket in the classic look, which stays the default." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/classic-desk-light.
|
|
73
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2024 Stanley Cup playoffs: Florida and Edmonton, each one's three series with the games won between the two logos." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-wide-nhl-light.
|
|
74
|
-
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a card." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-card-light.
|
|
72
|
+
<td align="center" valign="top"><img alt="The same bracket in the classic look, which stays the default." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/classic-desk-light.webp" width="460"><br><em>The classic look, still the default.</em></td>
|
|
73
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2024 Stanley Cup playoffs: Florida and Edmonton, each one's three series with the games won between the two logos." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-wide-nhl-light.webp" width="460"><br><em>The road to the final, a play-off (NHL 2024).</em></td>
|
|
74
|
+
<td align="center" valign="top"><img alt="The road to the final of the 2022 World Cup on a card." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/road-card-light.webp" width="260"><br><em>The road to the final, a card.</em></td>
|
|
75
75
|
</tr>
|
|
76
76
|
</table>
|
|
77
77
|
|
|
78
|
+
## Layouts
|
|
79
|
+
|
|
80
|
+
`layout` draws the same ties another way: the default, `"tree"`, is the bracket above; the others are `"rows"`, `"shields"`, `"update"`, `"columns"`, `"playin"`, `"series"` and `"groups"`. Each takes the `background`, both looks, the four sizes, the five languages, `href` links, seeds, codes, flags and logos, and a team with no picture is its tile. [docs/layouts.md](./docs/layouts.md) has the options and what each needs.
|
|
81
|
+
|
|
82
|
+
### rows
|
|
83
|
+
|
|
84
|
+
Each team a row, its name on the left and its mark on the right, its seed tag at the outer corner, and a slot for the result at the end that faces the centre (empty until the tie is played): the NHL poster's style.
|
|
85
|
+
|
|
86
|
+
<p align="center"><img alt="The 2024 NHL playoffs as rows: each team's abbreviation and seed tag, its logo tile and a slot with the games won, on an ice background." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-rows-nhl.webp" width="640"></p>
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
90
|
+
|
|
91
|
+
const ties = [
|
|
92
|
+
{ id: "a", sides: ["BOS", "MIA"], round: 1, bestOf: 7, score: [4, 1] },
|
|
93
|
+
{ id: "b", sides: ["NYK", "IND"], round: 1, bestOf: 7, score: [4, 3] },
|
|
94
|
+
{ id: "c", sides: ["BOS", "NYK"], round: 2, bestOf: 7, score: [2, 1] },
|
|
95
|
+
];
|
|
96
|
+
const svg = drawBracket(ties, { layout: "rows", look: "road", seeds: true });
|
|
97
|
+
console.log(svg.includes("tb-slot")); // true
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### shields
|
|
101
|
+
|
|
102
|
+
Marks in shield shapes with "vs" between the two of a tie, the matchups listed down both sides of the trophy; no connector lines.
|
|
103
|
+
|
|
104
|
+
<p align="center"><img alt="The 2022 World Cup as shields: each tie two round flags in shields with vs between them and the score under each, the final under the trophy." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-shields-wc2022.webp" width="640"></p>
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
108
|
+
|
|
109
|
+
const svg = drawBracket([{ sides: ["ARG", "FRA"], score: [3, 3], pens: [4, 2] }], { layout: "shields" });
|
|
110
|
+
console.log(svg.includes("tb-shield"), svg.includes(">vs<")); // true true
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### update
|
|
114
|
+
|
|
115
|
+
A compact score-update card: each side's abbreviation, seed and series score, and empty cards for the rounds still to come, the final in the centre. Put the "as of" date in `subtitle`.
|
|
116
|
+
|
|
117
|
+
<p align="center"><img alt="A score-update card of the 2024 NHL playoffs: abbreviations with seeds and the games won in a cell on the right, on an aurora background." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-update-nhl.webp" width="640"></p>
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
121
|
+
|
|
122
|
+
const teams = [{ id: "A", name: "Alpha", abbr: "ALP", seed: 1 }, { id: "B", name: "Beta", abbr: "BET", seed: 8 }];
|
|
123
|
+
const svg = drawBracket({ teams, matchups: [{ sides: ["A", "B"], round: 1, bestOf: 7, score: [4, 2] }] }, { layout: "update", subtitle: "as of May 1" });
|
|
124
|
+
console.log(svg.includes(">ALP<"), svg.includes(">as of May 1<")); // true true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### columns
|
|
128
|
+
|
|
129
|
+
The NFL poster's style: each round a column of tall slots that get taller toward the centre, one conference in each of two colours, a "VS" tag between the two slots of a tie, a big seed number beside a team that has a `seed`, and the final as two tall slots side by side. `at: true` writes the language's "AT" in place of "VS", the second side being the one at home (or the side `Matchup.home` names). `headers: true` adds the conference tiles.
|
|
130
|
+
|
|
131
|
+
<p align="center"><img alt="The 2024 NFL playoffs as columns: tall slots growing toward the centre, the AFC in blue and the NFC in red, VS tags between the slots, the Super Bowl as two tall slots, with a title tile over each half." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-columns-nfl.webp" width="640"></p>
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
135
|
+
|
|
136
|
+
const ties = [{ sides: ["KC", "BUF"], round: 1, score: [27, 24], home: 0 }, { sides: ["PHI", "WAS"], round: 1, score: [28, 23] }];
|
|
137
|
+
const svg = drawBracket(ties, { layout: "columns", at: true });
|
|
138
|
+
console.log(svg.includes(">AT<"), svg.includes(">VS<")); // true false
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### playin
|
|
142
|
+
|
|
143
|
+
The NBA's play-in: the games of each half (a `stage: "play-in"` tie), with a **winner's arrow solid and a loser's dashed**, into the game that takes it ("Winner 9/10", "Loser 7/8") or the seed it earns, and the seeds that need no game as tiles. A tie says where a side comes from with `feeds`, whose entries can now be `{ tie, result: "winner" | "loser" }`; `Tie.from` has it back.
|
|
144
|
+
|
|
145
|
+
<p align="center"><img alt="The 2024 NBA play-in: for each conference the 7 v 8 and 9 v 10 games, a dashed arrow for the 7 v 8 loser into the decider with the 9 v 10 winner, and a solid arrow into the 7th and 8th seed slots, beside tiles for seeds 1 to 6." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-playin-nba.webp" width="640"></p>
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
import { drawBracket, layoutBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
149
|
+
|
|
150
|
+
const matchups = [
|
|
151
|
+
{ id: "p78", stage: "play-in", sides: ["T7", "T8"], score: [105, 104], seeds: [7, 8] },
|
|
152
|
+
{ id: "p910", stage: "play-in", sides: ["T9", "T10"], score: [131, 116], seeds: [9, 10] },
|
|
153
|
+
{ id: "dec", stage: "play-in", sides: ["T8", "T9"], score: [112, 91], feeds: [{ tie: "p78", result: "loser" }, { tie: "p910", result: "winner" }] },
|
|
154
|
+
];
|
|
155
|
+
console.log(JSON.stringify(layoutBracket({ matchups }).ties[2].from)); // [{"tie":0,"result":"loser"},{"tie":1,"result":"winner"}]
|
|
156
|
+
console.log(drawBracket({ matchups }, { layout: "playin" }).includes("tb-arrow-loser")); // true
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### series
|
|
160
|
+
|
|
161
|
+
A tall card of one line a series, "BOS 4–0 MIA", the winner bold, the seeds at the line's ends, the east on top and the west below with the final in the middle. It is a card (1080 by 1350) unless a `size` is asked for.
|
|
162
|
+
|
|
163
|
+
<p align="center"><img alt="The 2024 NBA playoffs as a series card: the Eastern Conference on top, one line a series such as BOS 4-1 MIA, the final in the middle and the Western Conference below, on a carbon background." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-series-nba.webp" width="360"></p>
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
167
|
+
|
|
168
|
+
const svg = drawBracket([{ sides: ["BOS", "MIA"], round: 1, bestOf: 7, score: [4, 0] }], { layout: "series" });
|
|
169
|
+
console.log(svg.includes('viewBox="0 0 1080 1350"'), svg.includes(">4–0<")); // true true
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### groups
|
|
173
|
+
|
|
174
|
+
The group stage as one card a group: a title tile ("Group A"), a row a team with its flag or mark, its name and its record, the places that go through marked. The standings are worked out from the round-robin games (`round: 0`); `standings: "record"` is wins and losses (softball's), and `"points"` (the default) played, won, drawn, lost, goal difference and points. `qualify: 2` marks the top two of each group.
|
|
175
|
+
|
|
176
|
+
<p align="center"><img alt="The group stage of a made-up cup: four cards, each with a title tile and four teams with their marks and played, won, drawn, lost, goal difference and points, the top two of each marked." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-groups-cup.webp" width="640"></p>
|
|
177
|
+
|
|
178
|
+
<p align="center"><img alt="Softball pool play on a phone: three cards of four teams with their wins and losses, the top two of each marked, on a royal background." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-groups-softball.webp" width="260"></p>
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
import { drawBracket, groupStandings } from "@johnmorrisdotca/taisen-brackets";
|
|
182
|
+
|
|
183
|
+
const games = [
|
|
184
|
+
{ sides: ["A", "B"], round: 0, score: [2, 0] }, { sides: ["A", "C"], round: 0, score: [1, 1] }, { sides: ["B", "C"], round: 0, score: [0, 3] },
|
|
185
|
+
];
|
|
186
|
+
console.log(groupStandings({ matchups: games })[0].rows.map((r) => `${r.team.id} ${r.points}`).join(", ")); // C 4, A 4, B 0
|
|
187
|
+
console.log(drawBracket({ matchups: games }, { layout: "groups", qualify: 2 }).includes("Group A")); // true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Conference headers, a lone final, one stylesheet
|
|
191
|
+
|
|
192
|
+
`headers: true` puts a big title tile over each half (West and East, AFC and NFC) in the colour of that half, in any layout. A tournament that ended with a lone final and a third-place match (the World Cups of 1974 and 1978) is drawn with them centred, the champion over the final. And two sizes of the same bracket on one page can share one stylesheet: `styleScope` names the class that carries the rules, `style: false` leaves the `<style>` out of the second drawing, and `bracketStyle(options)` is the stylesheet for a page that writes it once itself.
|
|
193
|
+
|
|
194
|
+
<p align="center"><img alt="A lone final and a third-place match, centred: the champion above the final, the third place under it, on a pitch background." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/layout-lone-final.webp" width="560"></p>
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
import { bracketStyle, drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
198
|
+
|
|
199
|
+
const ties = [{ sides: ["A", "B"], round: 1, score: [2, 1] }];
|
|
200
|
+
const desk = drawBracket(ties, { styleScope: "mine", size: "wide" });
|
|
201
|
+
const phone = drawBracket(ties, { styleScope: "mine", size: "phone", style: false });
|
|
202
|
+
console.log(desk.includes("<style>"), phone.includes("<style>"), desk.includes(bracketStyle({ styleScope: "mine" }))); // true false true
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Backgrounds
|
|
206
|
+
|
|
207
|
+
`background` draws a poster background under the bracket: a gradient, a glow, a pattern or the markings of a playing surface, all drawn in code, each in a dark and a light variant. The text, the lines, the boxes and the marks take the colours that read over it. The plain colour stays the default.
|
|
208
|
+
|
|
209
|
+
<p align="center">
|
|
210
|
+
<picture>
|
|
211
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/backgrounds-dark.webp">
|
|
212
|
+
<img alt="The twenty-five backgrounds in a grid of five by five, each behind a different bracket: midnight, crimson, royal, emerald, pitch, ice, hardwood, infield, turf, ball-panels, swirl, waves, glow, floodlights, confetti, carbon, aurora, sunburst, chevrons, halftone, argyle, contour, stardust, mesh and spotlight." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/backgrounds-light.webp" width="900">
|
|
213
|
+
</picture>
|
|
214
|
+
</p>
|
|
215
|
+
|
|
216
|
+
The twenty-five: `midnight`, `crimson`, `royal`, `emerald`, `pitch` (soccer), `ice` (hockey), `hardwood` (basketball), `infield` (baseball), `turf` (football), `ball-panels`, `swirl`, `waves`, `glow`, `floodlights`, `confetti`, `carbon`, `aurora`, `sunburst`, `chevrons`, `halftone`, `argyle`, `contour`, `stardust`, `mesh` and `spotlight`. [docs/backgrounds.md](./docs/backgrounds.md) says what each is.
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
import { drawBracket } from "@johnmorrisdotca/taisen-brackets";
|
|
220
|
+
|
|
221
|
+
const ties = [
|
|
222
|
+
{ sides: ["VAN", "NSH"], score: [4, 3], round: 1, seeds: ["P1", "WC2"] },
|
|
223
|
+
{ sides: ["EDM", "LAK"], score: [1, 2], round: 1, seeds: ["P2", "P3"] },
|
|
224
|
+
{ sides: ["VAN", "LAK"], score: [2, 1], round: 2 },
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
// A preset by name; with `theme: "auto"` (the default) both variants are drawn and the page's own light or dark shows the right one.
|
|
228
|
+
const ice = drawBracket(ties, { look: "road", background: "ice", seeds: true });
|
|
229
|
+
|
|
230
|
+
// A preset, tuned: your own colours, the angle, how strong the pattern is, a seed for the scattered parts.
|
|
231
|
+
const mine = drawBracket(ties, { look: "road", theme: "dark", background: { preset: "swirl", colors: ["#10203a", "#3a1060", "#ff7ac8", "#6ae0ff"], angle: 135, intensity: 0.8 } });
|
|
232
|
+
|
|
233
|
+
// Your own picture, under a veil (http(s), relative or data:image/ only).
|
|
234
|
+
const photo = drawBracket(ties, { look: "road", theme: "dark", background: { image: "stadium.jpg", fit: "cover", dim: 0.55 } });
|
|
235
|
+
|
|
236
|
+
console.log(ice.includes("tb-bgd"), mine.includes("#ff7ac8"), photo.includes('<image href="stadium.jpg"')); // true true true
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
In the road look, `seeds: true` writes a small tag (`P1`, `WC2`) beside each team's mark, `codes: true` its three letters under the mark in a box of marks, `vs: true` a "v" between the two marks, and a team with no flag or logo is a tile with its letters. [docs/backgrounds.md](./docs/backgrounds.md) has the options, the contrast rules and the module the other packages of the family share.
|
|
240
|
+
|
|
78
241
|
## In 30 seconds
|
|
79
242
|
|
|
80
243
|
```sh
|
|
@@ -110,6 +273,10 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
|
|
|
110
273
|
- **Wide, square, card, phone**: 1200 by 675, 1080 by 1080, 1080 by 1350 (a tall post), or 390 wide and as tall as it needs; the rounds are columns, or rows on a phone and a card. Boxes show names and scores, abbreviations, or only the marks, whichever fits.
|
|
111
274
|
- **The road look**: `look: "road"` draws large round flags or crests, big bold scores with the loser's quiet, the rounds named on pills, and, for one team, its path through the bracket as a dotted line. It is the look of the road-to-the-final chart below, and every other option works with it.
|
|
112
275
|
- **The road to the final**: `roadToFinal` draws the two finalists of the tournament you already have, with the ties each played on the way and the score between their flags, on a card, a square, wide or a phone.
|
|
276
|
+
- **Poster backgrounds**: twenty-five, drawn in code, each in a dark and a light variant, among them the playing surfaces of hockey, basketball, baseball, football and soccer; your own colours, or your own picture; and the text, lines and boxes take the colours that read over them (4.5 to 1, held by a test).
|
|
277
|
+
- **Seed tags, codes and a "vs"** in the road look, and a team with no picture drawn as a tile with its letters, so that nothing looks missing.
|
|
278
|
+
- **Eight layouts**: `layout` draws the same ties as the tree, as `rows` (a name, a mark and a result slot a team), `shields`, a score-`update` card, tall `columns` in two conference colours, the NBA's `playin` with winners' and losers' arrows, a `series` card, or the `groups` tables; with big conference `headers` over each half in any of them, a lone final centred, and one stylesheet for several drawings (`styleScope`, `style: false`).
|
|
279
|
+
- **Nothing sticks out**: marks, text and round names stay inside their boxes and off the connector lines, in every size and both looks, held by a geometry test.
|
|
113
280
|
- **A link on every box**: `href: (tie, side?) => address` makes each tie's box (or each team's row) a real `<a>` in the SVG with an accessible name.
|
|
114
281
|
- **Flags from a plug-in**: a team's `flag` code is drawn by the `flags` function you pass (Hata's round flags are one line), with no dependency added.
|
|
115
282
|
- **Light, dark, poster**: every colour is a CSS custom property with a fallback, so the drawing follows the page's `prefers-color-scheme` or `data-theme` and can be restyled from outside.
|
|
@@ -119,7 +286,7 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
|
|
|
119
286
|
- **Formats by era**: NHL, NBA, MLB, NFL, CFL, MLS and FIFA World Cup round names, series lengths and byes.
|
|
120
287
|
- **Five languages**: English, French, Japanese, Spanish and German, for every word the drawing, the tooltips, the description and the table write, with the football terms of each language; countries named by `Intl` from their ISO code; numbers and dates by `Intl`. Add a language of your own.
|
|
121
288
|
- **Deterministic**: no clock, no random number, no counter; the same input gives the same string, and ids come from a hash of the input.
|
|
122
|
-
- **No dependencies**, ESM with types, about
|
|
289
|
+
- **No dependencies**, ESM with types, about 140 kB packed.
|
|
123
290
|
|
|
124
291
|
## Use it in your project
|
|
125
292
|
|
|
@@ -131,7 +298,7 @@ npm install @johnmorrisdotca/taisen-brackets
|
|
|
131
298
|
# or: yarn add @johnmorrisdotca/taisen-brackets
|
|
132
299
|
```
|
|
133
300
|
|
|
134
|
-
It is ESM, and `require` works on Node 22.12 and later. It needs no DOM: the functions return strings.
|
|
301
|
+
It is ESM, and `require` works on Node 22.12 and later. It needs no DOM: the functions return strings. Five entry points: `@johnmorrisdotca/taisen-brackets` (everything), `/layout` (the layout and the helpers, no drawing), `/presets` (the formats), `/road` (the road to the final) and `/backgrounds` (the twenty-five backgrounds on their own).
|
|
135
302
|
|
|
136
303
|
## Examples
|
|
137
304
|
|
|
@@ -465,8 +632,10 @@ The string is built from your data, with every name escaped; do not put untruste
|
|
|
465
632
|
|
|
466
633
|
Everything is exported from `@johnmorrisdotca/taisen-brackets`; the layout part from `/layout`, the formats from `/presets`. The types are in the package; each function's doc comment has its details.
|
|
467
634
|
|
|
468
|
-
- `drawBracket(input, options?)`: the SVG string. `input` is a list of matchups, `{ matchups, teams }` or a layout. Options: `size`, `orientation`, `shape`, `detail`, `theme`, `background`, `title`, `subtitle`, `roundNames`, `roundLabels`, `scores`, `seeds`, `markShape`, `champion`, `trophy`, `emblems`, `emblemStyle`, `emblemTint`, `thirdPlace`, `winnerHighlight`, `look`, `href`, `highlightPath`, `flags`, `locale`, `words`, `teamName`, `groupOrder`, `id`, `className`.
|
|
635
|
+
- `drawBracket(input, options?)`: the SVG string. `input` is a list of matchups, `{ matchups, teams }` or a layout. Options: `layout`, `headers`, `at`, `standings`, `qualify`, `style`, `styleScope`, `size`, `orientation`, `shape`, `detail`, `theme`, `background` (a preset's name, a tuned preset or your own picture), `vs`, `codes`, `title`, `subtitle`, `roundNames`, `roundLabels`, `scores`, `seeds`, `markShape`, `champion`, `trophy`, `emblems`, `emblemStyle`, `emblemTint`, `thirdPlace`, `winnerHighlight`, `look`, `href`, `tieClass`, `highlightPath`, `flags`, `flagHref`, `locale`, `words`, `teamName`, `groupOrder`, `id`, `className`.
|
|
469
636
|
- `roadToFinal(input, options?)`: the road to the final of a tournament or of two finalists: `{ options, title, summary, totals, draw(extra?), table(options?) }`. `input` is what `drawBracket` takes, or the two finalists with their paths. Options: `team`, `title`, `subtitle`, `final`, `labels`, `groupLabel`, `size`, `winner`, `codes`, `endnote`, and `locale`, `words`, `teamName`, `roundNames`, `markShape`, `flags`, `theme`, `background`, `id`, `className` as for `drawBracket`. The types `RoadChart`, `RoadFinalist`, `RoadMatch`, `RoadOptions` and the rest are exported too; it is also the one export of `/road`.
|
|
637
|
+
- `groupStandings(input, options?)`, `groupsTable(input, options?)`: the group stage's tables as data (`GroupTable`, `GroupRow`) and as HTML, from the round-robin games.
|
|
638
|
+
- `bracketStyle(options)`: the stylesheet of a drawing with those options and a `styleScope`, for a page that draws a bracket twice. `LAYOUTS` lists the layouts, `CONFERENCE_COLORS` the two half colours of the layouts that colour them (`--tb-conf-a` and `--tb-conf-b`).
|
|
470
639
|
- `layoutBracket(input, options?)`: the rounds, halves, rows, byes and results, without drawing. `shape: "ltr"` and `groupOrder` are its options.
|
|
471
640
|
- `bracketTable(input, options?)`: the HTML table.
|
|
472
641
|
- `describeBracket(input, options?)`: the sentence a screen reader gets.
|
|
@@ -478,6 +647,7 @@ Everything is exported from `@johnmorrisdotca/taisen-brackets`; the layout part
|
|
|
478
647
|
- `roundName(remaining)`, `roundNamesFor(count)`, `roundLabel(layout, round, names, words)`: round names.
|
|
479
648
|
- `LOCALES`, `LOCALE_CODES`, `defineLocale`, `localeOf`, `voiceOf`, `countryName`: the languages (see Languages), a language of your own, the formats and the names of countries from `Intl`. `localizedLayout(layout, voice)` is a layout with the team names in a language.
|
|
480
649
|
- `SIZES`, `THEMES`, `ROAD_THEMES`, `WORDS`, `VERSION`: the sizes (`wide`, `square`, `card`, `phone`), the looks' colours, the road look's extra colours, the English words, the version.
|
|
650
|
+
- `BACKGROUND_PRESETS`, `backgroundSvg(preset, options)`, `contrastRatio(a, b)`, `resolveBackground(option, theme, width, height, prefix)`, `FAMILY_BACKGROUNDS_VERSION`: the twenty-five backgrounds, one drawn on its own with the ink that reads over it, the contrast of two colours, the `background` option read, and the version of the file shared with the family (see "Backgrounds"). Also its own entry point, `/backgrounds`.
|
|
481
651
|
- `cleanSvg(markup)`, `safeUrl(url)`, `safeHref(url)`, `abbreviate(name)`: the rules for marks and for the addresses of links, and the short name made from a name. The types `FlagRenderer`, `FlagRequest` and `FlagShape` are the flags plug-in's (see "Flags from a plug-in").
|
|
482
652
|
|
|
483
653
|
## Languages
|
|
@@ -500,7 +670,7 @@ for (const locale of ["en", "fr", "ja", "es", "de"]) console.log(describeBracket
|
|
|
500
670
|
// 2 Teams, 1 Runde. Finale: Argentinien 3, Frankreich 3 (nach Verlängerung, 4:2 im Elfmeterschießen). Sieger: Argentinien. Turniersieger: Argentinien.
|
|
501
671
|
```
|
|
502
672
|
|
|
503
|
-
<p align="center"><img alt="The same bracket, the World Cup of 2022 on a phone's layout, in English, French, Japanese, Spanish and German side by side: the rounds, the notes, the label under the champion and the names of the countries are each in their language." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/languages-wc2022.
|
|
673
|
+
<p align="center"><img alt="The same bracket, the World Cup of 2022 on a phone's layout, in English, French, Japanese, Spanish and German side by side: the rounds, the notes, the label under the champion and the names of the countries are each in their language." src="https://raw.githubusercontent.com/johnmorrisdotca/taisen-brackets/main/docs/images/languages-wc2022.webp" width="900"></p>
|
|
504
674
|
|
|
505
675
|
- `locale` is `"en"` (the default), `"fr"`, `"ja"`, `"es"`, `"de"`, or a `Locale` you made with `defineLocale`. It sets the words, the names of the rounds, the `lang` of the `<svg>` and of the `<table>`, the digits and the dates (`Intl`), and capitals by the language's rules (not for Japanese). `LOCALES` holds the tables and `LOCALE_CODES` lists the codes.
|
|
506
676
|
- **Round names** are the football terms of each language's Wikipedia article on the World Cup: *Huitièmes de finale*, *Octavos de final*, *Achtelfinale*, ラウンド16; the leagues' rounds (NHL, NBA, MLB, NFL, CFL) are the generic words translated, and a league's own name is kept in the form the language uses (*Finale de la Coupe Stanley*, *Stanley-Cup-Finale*, *Coupe Grey*, *Super Bowl*, スーパーボウル). [docs/languages.md](./docs/languages.md) lists every term, what it was checked against, and what still needs a native reader (Spanish and German).
|
|
@@ -546,7 +716,7 @@ The names are `bg`, `ink`, `muted`, `line`, `box`, `edge`, `win`, `gold`, `plain
|
|
|
546
716
|
|
|
547
717
|
## Limits
|
|
548
718
|
|
|
549
|
-
- A bracket is a tree: every tie feeds one tie. Double elimination
|
|
719
|
+
- A bracket is a tree: every tie feeds one tie. Double elimination is not drawn. A loser can go on to another tie (`feeds: [{ tie, result: "loser" }]`), but only the play-in layout draws that edge; round-robin games (`round: 0`) are drawn as group tables by the `groups` layout, and below the tree by the others.
|
|
550
720
|
- Text is measured by an estimate from character classes, not a font file, so that the string is the same on every machine; a long name is cut with an ellipsis a few percent early or late.
|
|
551
721
|
- A series with no `bestOf` and no winner is not decided, whatever the games won say.
|
|
552
722
|
- On a phone the champion is at the top and the third-place match at the foot; in a wide bracket of two halves they are in the centre.
|
|
@@ -562,10 +732,11 @@ Any current browser, and Node 22 or later. The package makes no network request
|
|
|
562
732
|
|
|
563
733
|
## Roadmap
|
|
564
734
|
|
|
565
|
-
- Double elimination, and
|
|
735
|
+
- Double elimination, and the group tables on one page with the knockout they lead to.
|
|
566
736
|
- More languages (Portuguese, Italian, Korean, Chinese), and native review of the Spanish and German words.
|
|
567
737
|
- A custom element and a React helper, as in the other packages of the family.
|
|
568
738
|
- A PNG renderer (through an optional peer).
|
|
739
|
+
- See [docs/roadmap.md](./docs/roadmap.md) for what is planned; the pictures that prompted the layouts of 0.6.0 are listed in [docs/references.md](./docs/references.md).
|
|
569
740
|
|
|
570
741
|
## The name
|
|
571
742
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BackgroundInks } from "./theme.ts";
|
|
2
|
+
import type { ThemeName } from "./types.ts";
|
|
3
|
+
export interface ResolvedBackground {
|
|
4
|
+
/** For the drawing's `<defs>`. */
|
|
5
|
+
defs: string;
|
|
6
|
+
/** Drawn over the plain `.tb-bg` rectangle, under everything else. */
|
|
7
|
+
body: string;
|
|
8
|
+
/** The colours to draw over it: one for a look that is light or dark, both for `auto`. */
|
|
9
|
+
inks: BackgroundInks;
|
|
10
|
+
/** Both pictures are in the drawing and the stylesheet shows the one that fits. */
|
|
11
|
+
auto: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Whether an option asks for more than the plain colour: a preset, a tuned preset or an image. */
|
|
14
|
+
export declare function hasBackground(option: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Reads the `background` option for a drawing `width` by `height` in the look `theme`, with `prefix` for the ids. Returns `null` when the option is `true`, `false` or left out
|
|
17
|
+
* (a plain colour, or none). An unknown preset, a bad colour list or an image address that is not http(s), relative or `data:image/…` throws a `RangeError`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveBackground(option: unknown, theme: ThemeName, width: number, height: number, prefix: string): ResolvedBackground | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// The `background` option: a preset's name, a preset tuned, or the caller's own picture, turned into the SVG to draw under everything and the colours to draw over it.
|
|
2
|
+
// The drawing of the presets is `family-backgrounds.ts`, which is shared with the other packages of the family; this file only reads the option and writes the picture's frame.
|
|
3
|
+
import { BACKGROUND_PRESETS, backgroundSvg } from "./family-backgrounds.js";
|
|
4
|
+
import { safeUrl } from "./marks.js";
|
|
5
|
+
import { esc, num } from "./text.js";
|
|
6
|
+
const isPreset = (name) => typeof name === "string" && BACKGROUND_PRESETS.includes(name);
|
|
7
|
+
/** Whether an option asks for more than the plain colour: a preset, a tuned preset or an image. */
|
|
8
|
+
export function hasBackground(option) {
|
|
9
|
+
return typeof option === "string" || (typeof option === "object" && option !== null);
|
|
10
|
+
}
|
|
11
|
+
const fail = (message) => {
|
|
12
|
+
throw new RangeError(`taisen-brackets: ${message}`);
|
|
13
|
+
};
|
|
14
|
+
/** The ink for a picture of the caller's own: a plain dark or pale ground, since the image under the veil is not known. */
|
|
15
|
+
function inkForImage(theme, id) {
|
|
16
|
+
const colors = theme === "dark" ? ["#12161c", "#12161c", "#c9d2e0", "#c9d2e0"] : ["#f4f4f1", "#f4f4f1", "#4a5568", "#4a5568"];
|
|
17
|
+
return backgroundSvg("midnight", { width: 8, height: 8, theme, colors, id }).ink;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Reads the `background` option for a drawing `width` by `height` in the look `theme`, with `prefix` for the ids. Returns `null` when the option is `true`, `false` or left out
|
|
21
|
+
* (a plain colour, or none). An unknown preset, a bad colour list or an image address that is not http(s), relative or `data:image/…` throws a `RangeError`.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveBackground(option, theme, width, height, prefix) {
|
|
24
|
+
if (option === undefined || typeof option === "boolean" || option === null)
|
|
25
|
+
return null;
|
|
26
|
+
const spec = typeof option === "string" ? { preset: option } : option;
|
|
27
|
+
if (typeof option !== "string" && typeof option !== "object")
|
|
28
|
+
return fail(`background is a preset's name or an object, not ${typeof option}`);
|
|
29
|
+
const image = spec.image;
|
|
30
|
+
if (image === undefined && spec.preset !== undefined && !isPreset(spec.preset))
|
|
31
|
+
fail(`unknown background "${String(spec.preset)}": use one of ${BACKGROUND_PRESETS.join(", ")}`);
|
|
32
|
+
if (spec.colors !== undefined && (!Array.isArray(spec.colors) || spec.colors.some((c) => typeof c !== "string")))
|
|
33
|
+
fail("background.colors is a list of colours as text");
|
|
34
|
+
for (const key of ["angle", "intensity", "seed", "dim"])
|
|
35
|
+
if (spec[key] !== undefined && !Number.isFinite(spec[key]))
|
|
36
|
+
fail(`background.${key} is a number`);
|
|
37
|
+
// Which pictures to draw: the one the look is, or the one asked for; `auto` draws both.
|
|
38
|
+
const want = spec.theme ? [spec.theme] : theme === "light" ? ["light"] : theme === "dark" || theme === "poster" || theme === "none" ? ["dark"] : ["light", "dark"];
|
|
39
|
+
const auto = want.length === 2;
|
|
40
|
+
const parts = want.map((t) => {
|
|
41
|
+
const id = auto ? `${prefix}${t === "light" ? "l" : "d"}` : `${prefix}b`;
|
|
42
|
+
if (image !== undefined) {
|
|
43
|
+
if (typeof image !== "string" || !safeUrl(image))
|
|
44
|
+
return fail("background.image must be an http(s) address, a relative path or a data:image/ address");
|
|
45
|
+
const dim = Math.min(1, Math.max(0, spec.dim ?? 0.5));
|
|
46
|
+
const fitName = spec.fit === "contain" ? "meet" : "slice";
|
|
47
|
+
return {
|
|
48
|
+
t,
|
|
49
|
+
defs: "",
|
|
50
|
+
body: `<image href="${esc(image)}" x="0" y="0" width="${num(width)}" height="${num(height)}" preserveAspectRatio="xMidYMid ${fitName}"/><rect width="${num(width)}" height="${num(height)}" fill="${t === "dark" ? "#000" : "#fff"}" opacity="${num(dim)}"/>`,
|
|
51
|
+
ink: inkForImage(t, id),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const made = backgroundSvg(spec.preset ?? "midnight", { width, height, theme: t, colors: spec.colors, angle: spec.angle, intensity: spec.intensity, seed: spec.seed, id });
|
|
55
|
+
return { t, ...made };
|
|
56
|
+
});
|
|
57
|
+
const inks = {};
|
|
58
|
+
for (const p of parts)
|
|
59
|
+
inks[p.t] = p.ink;
|
|
60
|
+
return {
|
|
61
|
+
defs: parts.map((p) => p.defs).join(""),
|
|
62
|
+
body: auto ? parts.map((p) => `<g class="${p.t === "light" ? "tb-bgl" : "tb-bgd"}">${p.body}</g>`).join("") : parts[0].body,
|
|
63
|
+
inks,
|
|
64
|
+
auto,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BACKGROUND_PRESETS, FAMILY_BACKGROUNDS_VERSION, backgroundSvg, contrastRatio, luminance, parseColor, toHex } from "./family-backgrounds.js";
|