|
7 | 7 | <style> |
8 | 8 | /* Embedded styles for standalone viewing */ |
9 | 9 | .release-cycle-chart { |
10 | | - font-family: Arial, sans-serif; |
| 10 | + color-scheme: light; |
| 11 | +
|
| 12 | + {# Copy vars from Furo theme if present #} |
| 13 | + {% for varname, default in { |
| 14 | + 'color-foreground-primary': 'light-dark(#333, #fff)', |
| 15 | + 'color-background-primary': 'light-dark(#fff, #333)', |
| 16 | + 'color-brand-primary': '#4B8BBE', |
| 17 | + 'color-background-item': '#e0e0e0', |
| 18 | + }.items() %} |
| 19 | + --svg-{{varname}}: var(--{{varname}}, {{default}}); |
| 20 | + {% endfor %} |
| 21 | +
|
| 22 | + font-family: var( |
| 23 | + --font-stack, |
| 24 | + -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, |
| 25 | + Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji); |
11 | 26 | width: 100%; |
| 27 | +
|
| 28 | + --blob-border-width: 1.6px; |
| 29 | + } |
| 30 | + .background { |
| 31 | + fill: var(--svg-color-background-primary); |
12 | 32 | } |
13 | 33 | .release-cycle-year-line { |
14 | | - stroke: #333; |
| 34 | + stroke: var(--svg-color-foreground-primary); |
15 | 35 | stroke-width: 0.8px; |
16 | 36 | opacity: 75%; |
17 | 37 | } |
18 | | - .release-cycle-year-text { |
19 | | - fill: #333; |
20 | | - } |
21 | 38 | .release-cycle-today-line { |
22 | | - stroke: #4B8BBE; |
23 | | - stroke-width: 1.6px; |
| 39 | + stroke: var(--svg-color-brand-primary); |
| 40 | + stroke-width: var(--blob-border-width); |
24 | 41 | } |
25 | 42 | .release-cycle-row-shade { |
26 | | - fill: #e0e0e0; |
| 43 | + fill: var(--svg-color-background-item); |
27 | 44 | opacity: 50%; |
28 | 45 | } |
29 | | - .release-cycle-version-label { |
30 | | - fill: #333; |
31 | | - } |
32 | 46 | .release-cycle-blob { |
33 | | - stroke-width: 1.6px; |
| 47 | + stroke-width: var(--blob-border-width); |
34 | 48 | } |
35 | | - .release-cycle-blob-label { |
36 | | - /* white looks good on both light and dark */ |
37 | | - fill: white; |
| 49 | + .text-main { |
| 50 | + fill: var(--svg-color-foreground-primary); |
| 51 | +
|
| 52 | + /* use specific colours on known backgrounds */ |
| 53 | + &.release-cycle-status-security, |
| 54 | + &.release-cycle-status-bugfix { |
| 55 | + fill: black; |
| 56 | + } |
38 | 57 | } |
39 | | - .release-cycle-blob-label.release-cycle-status-security, |
40 | | - .release-cycle-blob-label.release-cycle-status-bugfix { |
41 | | - /* but use black to improve contrast for lighter backgrounds */ |
42 | | - fill: black; |
| 58 | + .text-outline { |
| 59 | + /* an outline of the background color, in case it's not set |
| 60 | + correctly */ |
| 61 | + fill: transparent; |
| 62 | + stroke: var(--svg-color-background-primary); |
| 63 | + stroke-width: var(--blob-border-width); |
| 64 | +
|
| 65 | + /* use specific colours on known backgrounds */ |
| 66 | + &.release-cycle-status-security, |
| 67 | + &.release-cycle-status-bugfix { |
| 68 | + stroke: var(--status-bg-color); |
| 69 | + } |
43 | 70 | } |
44 | | - .release-cycle-blob-label.release-cycle-status-end-of-life, |
45 | | - .release-cycle-blob-label.release-cycle-status-prerelease, |
46 | | - .release-cycle-blob-label.release-cycle-status-feature { |
47 | | - fill: #333; |
| 71 | + .release-cycle-status-end-of-life { |
| 72 | + --status-bg-color: #DD2200; |
| 73 | + --status-border-color: #FF8888; |
48 | 74 | } |
49 | | - .release-cycle-status-end-of-life .release-cycle-blob, |
50 | | - .release-cycle-blob.release-cycle-status-end-of-life { |
51 | | - fill: #DD2200; |
52 | | - stroke: #FF8888; |
| 75 | + .release-cycle-status-security { |
| 76 | + --status-bg-color: #FFDD44; |
| 77 | + --status-border-color: #FF8800; |
53 | 78 | } |
54 | | - .release-cycle-status-security .release-cycle-blob, |
55 | | - .release-cycle-blob.release-cycle-status-security { |
56 | | - fill: #FFDD44; |
57 | | - stroke: transparent; |
| 79 | + .release-cycle-status-bugfix { |
| 80 | + --status-bg-color: #00DD22; |
| 81 | + --status-border-color: #008844; |
58 | 82 | } |
59 | | - .release-cycle-status-bugfix .release-cycle-blob, |
60 | | - .release-cycle-blob.release-cycle-status-bugfix { |
61 | | - fill: #00DD22; |
62 | | - stroke: transparent; |
| 83 | + .release-cycle-status-prerelease { |
| 84 | + --status-bg-color: teal; |
| 85 | + --status-border-color: darkgreen; |
63 | 86 | } |
64 | | - .release-cycle-status-prerelease .release-cycle-blob, |
65 | | - .release-cycle-blob.release-cycle-status-prerelease { |
66 | | - fill: teal; |
67 | | - stroke: transparent; |
| 87 | + .release-cycle-status-feature { |
| 88 | + --status-bg-color: #2222EE; |
| 89 | + --status-border-color: #008888; |
68 | 90 | } |
69 | | - .release-cycle-status-feature .release-cycle-blob, |
70 | | - .release-cycle-blob.release-cycle-status-feature { |
71 | | - fill: #2222EE; |
| 91 | + .release-cycle-blob { |
| 92 | + fill: var(--status-bg-color); |
72 | 93 | stroke: transparent; |
73 | 94 | } |
74 | | - .release-cycle-blob-full.release-cycle-status-end-of-life { |
75 | | - fill: #DD2200; |
76 | | - stroke: #FF8888; |
77 | | - } |
78 | | - .release-cycle-border.release-cycle-status-security { |
79 | | - fill: transparent; |
80 | | - stroke: #FF8800; |
81 | | - stroke-width: 1.6px; |
82 | | - } |
83 | | - .release-cycle-border.release-cycle-status-bugfix { |
84 | | - fill: transparent; |
85 | | - stroke: #008844; |
86 | | - stroke-width: 1.6px; |
| 95 | + .release-cycle-blob-full { |
| 96 | + fill: var(--status-bg-color); |
| 97 | + stroke: var(--status-border-color); |
87 | 98 | } |
88 | | - .release-cycle-border.release-cycle-status-prerelease { |
| 99 | + .release-cycle-border { |
89 | 100 | fill: transparent; |
90 | | - stroke: darkgreen; |
91 | | - stroke-width: 1.6px; |
92 | | - } |
93 | | - .release-cycle-border.release-cycle-status-feature { |
94 | | - fill: transparent; |
95 | | - stroke: #008888; |
96 | | - stroke-width: 1.6px; |
| 101 | + stroke: var(--status-border-color); |
| 102 | + stroke-width: var(--blob-border-width); |
97 | 103 | } |
98 | 104 | </style> |
99 | 105 | <defs> |
|
103 | 109 | </linearGradient> |
104 | 110 | </defs> |
105 | 111 |
|
| 112 | + <rect |
| 113 | + class="background" |
| 114 | + x="0" |
| 115 | + y="0" |
| 116 | + width="{{ diagram_width }}" |
| 117 | + height="{{ diagram_height }}" |
| 118 | + /> |
| 119 | + |
106 | 120 | {% for version in versions %} |
107 | 121 | {% set y = version.y * line_height %} |
108 | | - |
109 | 122 | {% if version.y % 2 %} |
110 | 123 | <!-- Row shading --> |
111 | 124 | <rect |
|
120 | 133 |
|
121 | 134 | {% for year in years %} |
122 | 135 | <text |
123 | | - class="release-cycle-year-text" |
| 136 | + class="release-cycle-year-text text-main" |
124 | 137 | x="{{ (year_to_x(year) + year_to_x(year + 1)) / 2 }}" |
125 | 138 | y="{{ diagram_height - line_height }}" |
126 | 139 | font-size="{{ SCALE * 0.75 }}" |
|
166 | 179 | </mask> |
167 | 180 |
|
168 | 181 | {% for version in versions %} |
169 | | - <!-- Colourful blob with a label. --> |
| 182 | + <!-- Colourful blob. --> |
170 | 183 |
|
171 | 184 | {% set top_y = version.y * line_height - 1 * SCALE %} |
172 | 185 | {% set height = 1.25 * SCALE %} |
173 | 186 | {% set start_x = date_to_x(version.first_release_date) %} |
174 | 187 | {% set end_x = date_to_x(version.end_of_life_date) %} |
175 | 188 | {% set radius = 0.25 * SCALE %} |
176 | 189 |
|
177 | | - {% set small_text_y = version.y * line_height - 0.1 * SCALE %} |
178 | | - |
179 | 190 | <!-- bugfix/security blobs need to be split between the two phases. |
180 | 191 | Draw the rectangle with two path elements instead. |
181 | 192 | Thanks Claude.ai for the initial conversion. |
|
243 | 254 | mask="url(#release-cycle-mask-{{ id_key }})" |
244 | 255 | /> |
245 | 256 | {% endif %} |
| 257 | + {% endfor %} |
| 258 | + |
| 259 | + <!-- A line for today --> |
| 260 | + <line |
| 261 | + class="release-cycle-today-line" |
| 262 | + x1="{{ date_to_x(today) }}" |
| 263 | + x2="{{ date_to_x(today) }}" |
| 264 | + y1="0" |
| 265 | + y2="{{ diagram_height - line_height }}" |
| 266 | + font-size="{{ SCALE }}" |
| 267 | + /> |
| 268 | + |
| 269 | + {% for version in versions %} |
| 270 | + <!-- Label for colourful blob --> |
| 271 | + |
| 272 | + {% set start_x = date_to_x(version.first_release_date) %} |
| 273 | + {% set end_x = date_to_x(version.end_of_life_date) %} |
| 274 | + {% set middle_x = ([end_x, date_to_x(version.start_security_date)]|min) %} |
| 275 | + {% set small_text_y = version.y * line_height - 0.1 * SCALE %} |
246 | 276 |
|
247 | 277 | <!-- Add text before/after/inside the blob --> |
248 | | - <text |
249 | | - class="release-cycle-blob-label release-cycle-status-{{ version.status }}" |
250 | | - font-size="{{ SCALE * 0.75 }}" |
251 | | - y="{{ small_text_y }}" |
252 | | - {% if version.status == "bugfix" %} |
253 | | - x="{{ (start_x + middle_x) / 2 }}" |
254 | | - text-anchor="middle" |
255 | | - {% elif version.status == "security" %} |
256 | | - x="{{ (middle_x + end_x) / 2 }}" |
257 | | - text-anchor="middle" |
258 | | - {% elif version.status == "end-of-life" %} |
259 | | - x="{{ end_x + (0.25 * SCALE) }}" |
260 | | - text-anchor="start" |
261 | | - {% else %} |
262 | | - x="{{ start_x - (0.25 * SCALE) }}" |
263 | | - text-anchor="end" |
264 | | - {% endif %} |
265 | | - > |
266 | | - {{ version.status }} |
267 | | - </text> |
| 278 | + {% for cls in ('text-outline', 'text-main') %} |
| 279 | + <text |
| 280 | + class="release-cycle-blob-label {{cls}} release-cycle-status-{{ version.status }}" |
| 281 | + font-size="{{ SCALE * 0.75 }}" |
| 282 | + y="{{ small_text_y }}" |
| 283 | + {% if version.status == "bugfix" %} |
| 284 | + x="{{ (start_x + middle_x) / 2 }}" |
| 285 | + text-anchor="middle" |
| 286 | + {% elif version.status == "security" %} |
| 287 | + x="{{ (middle_x + end_x) / 2 }}" |
| 288 | + text-anchor="middle" |
| 289 | + {% elif version.status == "end-of-life" %} |
| 290 | + x="{{ end_x + (0.25 * SCALE) }}" |
| 291 | + text-anchor="start" |
| 292 | + {% else %} |
| 293 | + x="{{ start_x - (0.25 * SCALE) }}" |
| 294 | + text-anchor="end" |
| 295 | + {% endif %} |
| 296 | + > |
| 297 | + {{ version.status }} |
| 298 | + </text> |
| 299 | + {% endfor %} |
268 | 300 |
|
269 | 301 | <!-- Legend on the left --> |
270 | 302 | <text |
271 | | - class="release-cycle-version-label" |
| 303 | + class="release-cycle-version-label text-main" |
272 | 304 | x="{{ 0.5 * SCALE }}" |
273 | 305 | y="{{ version.y * line_height }}" |
274 | 306 | font-size="{{ SCALE }}" |
275 | 307 | > |
276 | 308 | Python {{ version.key }} |
277 | 309 | </text> |
278 | 310 | {% endfor %} |
279 | | - |
280 | | - <!-- A line for today --> |
281 | | - <line |
282 | | - class="release-cycle-today-line" |
283 | | - x1="{{ date_to_x(today) }}" |
284 | | - x2="{{ date_to_x(today) }}" |
285 | | - y1="0" |
286 | | - y2="{{ diagram_height - line_height }}" |
287 | | - font-size="{{ SCALE }}" |
288 | | - /> |
289 | 311 | </svg> |
0 commit comments