Add alt-text to all images and consider captioning
Add alt-text to all images and consider captioning some of them. The caption is now in the place where the alt-text used to be, and the alt-text is in an extra attribute after the definition of the image (e.g. caption text{alt='Alt text'})
From some quick greping on the Markdown source in episodes it looks like all the current figures have alt text attributes set unless I'm misintrepreting (or this is intended to apply to files outside of episodes!):
Output of grep -E -r '\!\[.*\]\(.+\)' episodes
episodes/50-section5-intro.md:{alt='Managing software' .image-with-shadow width="1000px" }
episodes/14-collaboration-using-git.md:{alt='Development lifecycle with Git, containing Git commands add, commit, push, fetch, restore, merge and pull' .image-with-shadow width="600px"}
episodes/14-collaboration-using-git.md:{alt='git-distributed' .image-with-shadow width="400px"}
episodes/14-collaboration-using-git.md:{alt='Git feature branch workflow diagram' .image-with-shadow width="800px"}
episodes/14-collaboration-using-git.md:{alt="Software project's main branch" .image-with-shadow width="600px"}
episodes/14-collaboration-using-git.md:{alt="Software project's develop branch" .image-with-shadow width="600px"}
episodes/41-code-review.md:{alt='Code review process sequence' .image-with-shadow width="600px"}
episodes/41-code-review.md: {alt='GitHub pull requests tab' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='Creating a new pull request.' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='Submitting a pull request.' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='Adding a collaborator in GitHub' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='The files changed tab of a pull request' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='Adding a review comment to a pull request' .image-with-shadow width="800px"}
episodes/41-code-review.md: {alt='Adding a suggestion to a pull request' .image-with-shadow width="800px"}
episodes/41-code-review.md: {alt='Using the finishing your review dialog' .image-with-shadow width="800px"}
episodes/41-code-review.md: {alt='Using the finishing your review dialog' .image-with-shadow width="900px"}
episodes/41-code-review.md: {alt='Responding to a review comment with an emoji' .image-with-shadow width="800px"}
episodes/41-code-review.md: {alt='Responding to a review comment with a link to commit' .image-with-shadow width="800px"}
episodes/41-code-review.md: {alt='Merging a pull request in GitHub' .image-with-shadow width="800px"}
episodes/12-virtual-environments.md: (Creative Commons Attribution-NonCommercial 2.5 License)](fig/python-environment-hell.png){alt='Python environment hell XKCD comic'}
episodes/32-software-architecture-design.md:{alt='Writing good code comic' .image-with-shadow width="400px" }
episodes/32-software-architecture-design.md:{alt='Diagram showing proposed architecture of the problem' width="600px" }
episodes/00-setting-the-scene.md:{alt="Course overview diagram. Arrows connect the following boxed text in order: 1) Setting up software environment 2) Verifying software correctness 3) Software development as a process 4) Collaborative development for reuse 5) Managing software over its lifetime."}
episodes/23-continuous-integration-automated-testing.md:{alt='Continuous Integration with GitHub Actions - Initial Build' .image-with-shadow width="1000px"}
episodes/23-continuous-integration-automated-testing.md:{alt='Continuous Integration with GitHub Actions - Build Log' .image-with-shadow width="1000px"}
episodes/23-continuous-integration-automated-testing.md:{alt='Continuous Integration with GitHub Actions - Build Details' .image-with-shadow width="1000px"}
episodes/23-continuous-integration-automated-testing.md:{alt='Continuous Integration with GitHub Actions - Build Matrix' .image-with-shadow width="1000px"}
episodes/20-section2-intro.md:{alt='Tools for scaled software testing'}
episodes/13-ides.md:{alt='View of an opened project in PyCharm' .image-with-shadow width="1000px" }
episodes/13-ides.md:{alt='Missing Python Interpreter Warning in PyCharm' .image-with-shadow width="800px" }
episodes/13-ides.md: {alt='Configuring Python Interpreter in PyCharm' .image-with-shadow width="800px"}
episodes/13-ides.md:{alt='Packages Currently Installed in a Virtual Environment in PyCharm' .image-with-shadow width="800px"}
episodes/13-ides.md: {alt='Installing a package in PyCharm' .image-with-shadow width="800px" }
episodes/13-ides.md: {alt='Adding a Run Configuration in PyCharm' .image-with-shadow width="800px" }
episodes/13-ides.md: {alt='Run Configuration Popup in PyCharm' .image-with-shadow width="800px" }
episodes/13-ides.md:{alt='Syntax Highlighting Functionality in PyCharm' .image-with-shadow width="1000px" }
episodes/13-ides.md:{alt='Code Completion Functionality in PyCharm' .image-with-shadow width="600px" }
episodes/13-ides.md:{alt='Code References Functionality in PyCharm' .image-with-shadow width="1000px" }
episodes/13-ides.md: {alt='Code Search Functionality in PyCharm' .image-with-shadow width="800px" }
episodes/13-ides.md: {alt='Code Search Functionality in PyCharm' .image-with-shadow width="1000px" }
episodes/13-ides.md:{alt='Version Control Functionality in PyCharm' .image-with-shadow width="1000px" }
episodes/13-ides.md:{alt='Running a script from PyCharm' .image-with-shadow width="800px" }
episodes/53-improvement-through-feedback.md:{alt='Milestones in GitHub' .image-with-shadow width="1000px"}
episodes/53-improvement-through-feedback.md:{alt='Create a milestone in GitHub' .image-with-shadow width="1000px"}
episodes/53-improvement-through-feedback.md:{alt='Create a milestone in GitHub' .image-with-shadow width="800px"}
episodes/53-improvement-through-feedback.md:{alt='Milestones in GitHub' .image-with-shadow width="1000px"}
episodes/53-improvement-through-feedback.md:{alt='Milestones in Project Boards' .image-with-shadow width="900px"}
episodes/15-coding-conventions.md:{alt='Python code indentation settings in PyCharm' .image-with-shadow width="800px"}
episodes/15-coding-conventions.md:{alt='Python code whitespace settings in PyCharm' .image-with-shadow width="800px"}
episodes/10-section1-intro.md:{alt='Tools needed to collaborate on code development effectively'}
episodes/60-wrap-up.md:{alt='Usefulness versus time to master grid' .image-with-shadow width="800px"}
episodes/60-wrap-up.md:{alt='Overview of tools and techniques covered in the course' .image-with-shadow width="800px"}
episodes/60-wrap-up.md:{alt='Overview of topics covered in the course based on level of difficulty' .image-with-shadow width="800px"}
episodes/11-software-project.md:{alt='Snapshot of the inflammation dataset' .image-with-shadow width="800px" }
episodes/11-software-project.md: {alt='Software project fork repository in GitHub' .image-with-shadow width="900px" }
episodes/11-software-project.md: {alt='Making a fork of the software project repository in GitHub' .image-with-shadow width="600px" }
episodes/11-software-project.md: {alt='View of your own fork of the software repository in GitHub' .image-with-shadow width="900px" }
episodes/11-software-project.md:{alt='URL to clone the repository in GitHub' .image-with-shadow width="800px" }
episodes/40-section4-intro.md:{alt='Software design and architecture' .image-with-shadow width="1000px" }
episodes/51-managing-software.md:{alt='List of project issues in GitHub' .image-with-shadow width="1000px"}
episodes/51-managing-software.md:{alt='Creating a new issue in GitHub' .image-with-shadow width="1000px"}
episodes/51-managing-software.md:{alt='Referencing comments and commits in GitHub' .image-with-shadow width="700px"}
episodes/51-managing-software.md: {alt='Adding a new project board in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Selecting a project board template in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Project board setting in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Adding project description and metadata in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Default card board in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Adding issues and notes to a project board in GitHub' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Converting a task to issue' .image-with-shadow width="800px"}
episodes/51-managing-software.md: {alt='Add another project view' .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='NumPy arrays of incompatible shapes' .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt="NumPy arrays' shapes after adding a new\_axis" .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt="NumPy arrays' shapes after broadcasting" .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Setting up test framework in PyCharm' .image-with-shadow width="1000px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Running pytest in PyCharm' .image-with-shadow width="1000px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Ensuring testing configurations in PyCharm are correct' .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Running a single test in PyCharm' .image-with-shadow width="800px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Setting a breakpoint in PyCharm' .image-with-shadow width="600px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Debugging in PyCharm' .image-with-shadow width="1000px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='Debugging in PyCharm' .image-with-shadow width="1000px"}
episodes/24-diagnosing-issues-improving-robustness.md:{alt='All tests in PyCharm are successful' .image-with-shadow width="1000px"}
episodes/30-section3-intro.md:{alt='Software design and architecture overview flowchart'}
episodes/42-software-reuse.md:
(the instance in 42-software-reuse.md which appears not to have an alt-text set is actually embedded in a Markdown snippet as an example of creating a status badge so I assume not having an alt text here is intentional / correct)
Some of the existing alt-texts could possibly be expanded to be more descriptive, but I'm not sure if that is in scope for this issue @steve-crouch?
For the captions, do we want these for all figures? And in terms of differences between the caption and alt-text for a given image - my understanding would be the alt-text should describe the visual content of the image (to improve accessibility) while the caption is more about adding additional context / explanation about what is shown (without needing to recreate what is shown in the image) - does this sound reasonable?
I discussed this issue with @douglowe in the maintainers meeting on 2025-08-26 and showed an example of form of changes I was proposing for Collaboration with Git episode in 73f53de20a30028ea80a1c5c87742763a08eef1c - in summary making the alt-text a self-contained description of figure content. @douglowe agreed this seemed a good thing to do and suggested breaking down this issue with sub-issues for updating alt-texts on a per-episode basis to keep associated pull-requests smaller / more easily reviewed and also allow distributing the work.