Skip to content

Commit 13a34db

Browse files
authored
Add light dark image support (#1756)
1 parent e2adc94 commit 13a34db

3 files changed

Lines changed: 279 additions & 99 deletions

File tree

.github/workflows/guidelines.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,40 @@ Use these rules across workshop authoring/editing workflows to keep the tutorial
5353
- Do **not** number Markdown headers inside a file. Use descriptive headings such as `### Open the Codespace`, not `### 2. Open the Codespace`.
5454
- Keep ordering in ordered lists, tables, filenames, and checkpoint lists instead of in the heading text itself.
5555

56+
## Theme-aware workshop images
57+
58+
When Playwright or another automation creates a workshop screenshot or diagram,
59+
generate both light and dark variants during the same run. Name them
60+
`<stem>-light.<ext>` and `<stem>-dark.<ext>`, then use GitHub's
61+
[theme-aware `<picture>` pattern](https://github.blog/developer-skills/github/how-to-make-your-images-in-markdown-on-github-adjust-for-dark-mode-and-light-mode/#one-snippet-two-themes):
62+
63+
```html
64+
<picture>
65+
<source media="(prefers-color-scheme: dark)" srcset="images/<stem>-dark.svg">
66+
<source media="(prefers-color-scheme: light)" srcset="images/<stem>-light.svg">
67+
<img alt="Concise descriptive alt text" src="images/<stem>-light.svg">
68+
</picture>
69+
```
70+
71+
- Keep the fallback `<img>` and use the light variant as its `src`.
72+
- Put alt text on the fallback `<img>`; do not duplicate it on `<source>` elements.
73+
- Capture or render each variant with Playwright's matching `colorScheme` setting.
74+
- Verify in both color schemes that `currentSrc` selects the expected variant and
75+
that the image is nonblank, readable, and free of clipping or overflow.
76+
77+
Existing single-theme workshop images are migration candidates, not exceptions:
78+
79+
- Inventory Markdown image references and HTML `src`/`srcset` references so
80+
existing `<picture>` blocks remain auditable.
81+
- Migrate at most three existing visuals per automated pull request. Process core
82+
workshop pages before setup paths, advanced topics, and side quests.
83+
- Preserve each visual's stem and alt text while creating `-light` and `-dark`
84+
variants and replacing the original reference with the `<picture>` pattern.
85+
- Create a genuine theme-specific variant for UI screenshots and diagrams. A
86+
theme-neutral photo may use the same existing file for both `<source>` entries
87+
instead of duplicating the binary.
88+
- Do not delete an original asset until no Markdown or HTML reference uses it.
89+
5690
## Alert callouts: use `<details>` only for multi-line content
5791

5892
### Alert level ceiling

.github/workflows/workshop-explanatory-diagrams.md

Lines changed: 94 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ emoji: 🧠
33
name: Workshop Explanatory Diagram Generator
44
description: >
55
Daily workshop illustrator that finds one concept in the workshop worth
6-
explaining visually, generates a polished educational SVG diagram, and opens a
7-
PR with the new image and minimal markdown updates.
6+
explaining visually, generates or migrates a polished light/dark SVG diagram
7+
pair, and opens a PR with theme-aware markdown updates.
88
on:
99
schedule: daily
1010
workflow_dispatch:
@@ -64,6 +64,8 @@ steps:
6464
)
6565
6666
image_re = re.compile(r'!\[[^\]]*\]\(([^)]+)\)')
67+
picture_re = re.compile(r'<picture\b.*?</picture>', re.IGNORECASE | re.DOTALL)
68+
html_image_re = re.compile(r'\b(?:src|srcset)="([^"]+)"')
6769
heading_re = re.compile(r'^(##+)\s+(.*)$', re.MULTILINE)
6870
6971
file_summaries = []
@@ -74,11 +76,24 @@ steps:
7476
(line[2:].strip() for line in lines if line.startswith("# ")),
7577
path.stem,
7678
)
77-
images = [
79+
markdown_images = [
7880
match.group(1)
7981
for match in image_re.finditer(text)
8082
if not match.group(1).startswith(("http://", "https://"))
8183
]
84+
picture_blocks = picture_re.findall(text)
85+
picture_images = [
86+
match.group(1)
87+
for block in picture_blocks
88+
for match in html_image_re.finditer(block)
89+
if not match.group(1).startswith(("http://", "https://"))
90+
]
91+
images = list(dict.fromkeys(markdown_images + picture_images))
92+
theme_aware_picture_count = sum(
93+
'(prefers-color-scheme: light)' in block
94+
and '(prefers-color-scheme: dark)' in block
95+
for block in picture_blocks
96+
)
8297
headings = [
8398
{
8499
"level": len(match.group(1)),
@@ -95,6 +110,8 @@ steps:
95110
"word_count": len(re.findall(r"\S+", text)),
96111
"image_count": len(images),
97112
"images": images,
113+
"single_theme_images": markdown_images,
114+
"theme_aware_picture_count": theme_aware_picture_count,
98115
"headings": headings,
99116
}
100117
)
@@ -125,9 +142,9 @@ You are an educational illustrator for the **Learning GitHub Agentic Workflows**
125142
workshop.
126143

127144
Your job is to find exactly one workshop concept that would be easier to learn
128-
with a visual explanation, turn that concept into a polished SVG diagram, and
129-
open a draft pull request with the image and the smallest markdown edit needed to
130-
use it.
145+
with a visual explanation, or one existing single-theme explanatory diagram,
146+
turn it into a polished light/dark SVG pair, and open a draft pull request with
147+
the smallest Markdown edit needed to use it.
131148

132149
Create **at most one** pull request per run.
133150

@@ -153,10 +170,22 @@ Create **at most one** pull request per run.
153170

154171
---
155172

156-
## Pick one concept worth illustrating
173+
## Pick One Migration or Concept
174+
175+
Inspect the selected file's `single_theme_images` first:
157176

158-
Choose exactly one concept from the selected file that benefits from a conceptual
159-
visual sketch.
177+
1. Classify each existing image as an explanatory diagram, GitHub UI screenshot,
178+
or theme-neutral photo.
179+
2. If an explanatory diagram exists, select exactly one for migration and do not
180+
create a new concept in this run.
181+
3. Leave GitHub UI screenshots to `workshop-ui-screenshots`.
182+
4. A theme-neutral photo may be converted to a `<picture>` block that uses the
183+
same file for both theme sources; do not duplicate its binary.
184+
185+
If no existing image in the selected file needs migration, choose exactly one
186+
new concept worth illustrating.
187+
188+
Choose a concept that benefits from a conceptual visual sketch.
160189

161190
Good candidates:
162191

@@ -184,24 +213,27 @@ Prefer concepts that are:
184213

185214
---
186215

187-
## Create one SVG explanatory diagram
216+
## Create One Theme-Aware Diagram
188217

189-
Generate exactly one SVG file for the chosen concept.
218+
Generate exactly one light/dark SVG pair for the chosen concept or migration.
219+
For a migration, preserve the original content, geometry, stem, and alt text.
190220

191221
### SVG style rules
192222

193223
Match the visual family of the UI screenshot workflow while staying conceptual:
194224

195-
- Canvas: `1200 x 560`, `viewBox="0 0 1200 560"`
196-
- Background: `#f6f8fa`
197-
- Main diagram card: white panel with rounded corners and a subtle `#d0d7de`
198-
border
199-
- Use GitHub-aligned colors such as `#0969da`, `#1a7f37`, `#8250df`, `#bf8700`,
200-
`#cf222e`, `#57606a`, and `#24292f`
225+
- Canvas: `1200 x 560`, `viewBox="0 0 1200 560"` for both variants
226+
- Keep geometry, labels, and content identical across the pair
227+
- Light palette: background `#f6f8fa`, panel `#ffffff`, border `#d0d7de`,
228+
primary text `#24292f`, muted text `#57606a`, and accent `#0969da`
229+
- Dark palette: background `#0d1117`, panel `#161b22`, border `#30363d`,
230+
primary text `#f0f6fc`, muted text `#8b949e`, and accent `#2f81f7`
231+
- Adapt semantic success, attention, danger, and done colors for sufficient
232+
contrast in each theme
201233
- Use simple labeled boxes, arrows, chips, dashed groupings, and numbered badges
202234
- Keep labels short and learner-friendly
203235
- Add a short title inside the graphic and a short annotation below it
204-
- Add `role="img"` and `aria-label` matching the markdown alt text
236+
- Add `role="img"` and `aria-label` matching the Markdown alt text
205237
- Output valid, self-contained SVG only
206238

207239
### Diagram content rules
@@ -215,68 +247,79 @@ Match the visual family of the UI screenshot workflow while staying conceptual:
215247

216248
### Naming convention
217249

218-
Write the file under `workshop/images/` using the workshop step identifier plus a
219-
short concept slug.
250+
Write both files under `workshop/images/` using the workshop step identifier plus
251+
a short concept slug and theme suffix.
220252

221253
Examples:
222254

223255
- `workshop/13-schedule-it.md` + concept `schedule loop`
224-
`workshop/images/13-schedule-loop.svg`
256+
`workshop/images/13-schedule-loop-light.svg` and
257+
`workshop/images/13-schedule-loop-dark.svg`
225258
- `workshop/16-connect-data-source.md` + concept `step-to-agent flow`
226-
`workshop/images/16-step-agent-flow.svg`
259+
`workshop/images/16-step-agent-flow-light.svg` and
260+
`workshop/images/16-step-agent-flow-dark.svg`
227261

228262
If the first filename choice already exists for another concept, choose a more
229263
specific slug instead of overwriting unrelated work.
230264

231265
---
232266

233-
## Update markdown minimally
267+
## Update Markdown Minimally
234268

235-
After generating the SVG:
269+
After generating the SVG pair:
236270

237-
1. Insert exactly one markdown image reference in the source workshop file near
238-
the concept it explains.
271+
1. Insert or replace exactly one image reference in the source workshop file
272+
near the concept it explains.
239273
2. Use this format exactly:
240274

241-
```markdown
242-
![Concise descriptive alt text](images/<filename>.svg)
243-
```
275+
```html
276+
<picture>
277+
<source media="(prefers-color-scheme: dark)" srcset="images/<stem>-dark.svg">
278+
<source media="(prefers-color-scheme: light)" srcset="images/<stem>-light.svg">
279+
<img alt="Concise descriptive alt text" src="images/<stem>-light.svg">
280+
</picture>
281+
```
244282

245-
3. Keep the edit minimal and line-precise.
246-
4. If needed, add at most two short sentences to introduce the diagram.
247-
5. Do not reformat surrounding sections.
248-
6. Do not add more than one image per run.
283+
1. Use the light variant as the fallback `src`; put alt text only on `<img>`.
284+
2. Keep the edit minimal and line-precise.
285+
3. If needed, add at most two short sentences to introduce a new diagram.
286+
4. Do not reformat surrounding sections or migrate more than one image per run.
287+
5. Do not delete the original until no Markdown or HTML reference uses it.
249288

250289
---
251290

252-
## Render and QA the diagram
291+
## Render and QA the Diagram
253292

254-
After generating the SVG and updating markdown:
293+
After generating the SVG pair and updating Markdown:
255294

256295
1. Start a local static file server from the repository root so the new
257-
`workshop/images/*.svg` file is reachable on `http://127.0.0.1`.
258-
2. Use Playwright to render the new SVG in a browser tab.
259-
3. Check that all text stays inside its boxes, chips, badges, callouts, and
296+
`workshop/images/*.svg` files are reachable on `http://127.0.0.1`.
297+
2. Use Playwright with `colorScheme: "light"` to render the exact `<picture>`
298+
block and confirm its `currentSrc` ends with `-light.svg`.
299+
3. Repeat with `colorScheme: "dark"` and confirm `currentSrc` ends with
300+
`-dark.svg`.
301+
4. Capture both variants and check that the images are nonblank and all text
302+
stays inside its boxes, chips, badges, callouts, and
260303
other visual containers at normal browser zoom.
261-
4. If any label bleeds out of a box, revise the SVG before continuing by
262-
widening the shape, wrapping or shortening the text, adjusting spacing, or
263-
slightly reducing font size.
264-
5. Re-render after each fix until the final image is visually clean and easy to
265-
read.
304+
5. If any label bleeds out of a box, revise both SVGs before continuing by
305+
widening the shape, wrapping or shortening the text, adjusting spacing, or
306+
slightly reducing font size.
307+
6. Re-render after each fix until both variants are visually clean, readable,
308+
and selected in the intended theme.
266309

267310
Treat this render pass as required final QA for every generated diagram.
268311

269312
---
270313

271314
## Pull request requirements
272315

273-
If you generated a diagram, call `create-pull-request` with:
316+
If you generated or migrated a diagram, call `create-pull-request` with:
274317

275-
- **Title**: `Add explanatory SVG diagram for <concept>`
318+
- **Title**: `Add theme-aware explanatory diagram for <concept>`
276319
- **Body** summarizing:
277320
- which workshop file changed
278-
- which concept was illustrated
279-
- which SVG file was added
321+
- whether the change creates a concept or migrates an existing diagram
322+
- both SVG files added
280323
- why the diagram helps learners
281324

282325
---
@@ -295,8 +338,9 @@ Call `noop` with a concise explanation when:
295338
## Output quality requirements
296339

297340
- Make only one coherent diagram change set per run.
298-
- Keep the markdown edit smaller than the SVG addition.
299-
- Ensure the final SVG passes a Playwright render check with no text bleeding
300-
outside its visual containers.
341+
- Keep the Markdown edit smaller than the SVG additions.
342+
- Ensure both SVGs pass Playwright checks in their matching color schemes,
343+
including expected `currentSrc`, nonblank pixels, and no text bleeding.
344+
- Use a theme-aware `<picture>` block with the light variant as fallback.
301345
- Do not modify files outside `workshop/`.
302346
- Never use write tools other than `create-pull-request` and `noop`.

0 commit comments

Comments
 (0)