Skip to content

Add bulk "Generate Alt Text" action to Media Library#330

Merged
dkotter merged 19 commits intoWordPress:developfrom
zeus2611:feature/bulk-alt-text-generation
Apr 9, 2026
Merged

Add bulk "Generate Alt Text" action to Media Library#330
dkotter merged 19 commits intoWordPress:developfrom
zeus2611:feature/bulk-alt-text-generation

Conversation

@zeus2611
Copy link
Copy Markdown
Contributor

@zeus2611 zeus2611 commented Mar 20, 2026

What?

Closes #239

Adds a "Generate Alt Text" bulk action to the WordPress Media Library (list view). When one or more images are selected and the action is applied, alt text is generated sequentially for each image using the existing ai/alt-text-generation ability and saved directly to each attachment via the REST API. A live progress notice is shown while processing and replaced with a summary on completion.

Why?

Alt text generation for individual images already existed in the media modal and attachment edit screen, but there was no way to process multiple images at once. This extends the feature to support bulk workflows, addressing the remaining item from issue #239.

How?

PHP (includes/Experiments/Alt_Text_Generation/Alt_Text_Generation.php):

  • Registers "Generate Alt Text" in the Media Library bulk actions dropdown via the bulk_actions-upload filter.
  • Handles the action via handle_bulk_actions-upload: filters selected IDs to image attachments only, then appends ai_bulk_alt_text=1 and ai_attachment_ids=<ids> to the redirect URL.
  • Detects the redirect params on page load and enqueues/localizes a new alt-text-generation-bulk script with the attachment IDs and a wp_rest nonce.

JavaScript (src/experiments/alt-text-generation/bulk.ts):

  • On DOMContentLoaded, reads localized data and injects a dismissible WP admin notice.
  • Loops through attachment IDs sequentially, calling the existing runAbility('ai/alt-text-generation', { attachment_id }) utility for each.
  • Saves each generated alt text via apiFetch to /wp/v2/media/:id.
  • Updates progress count in the notice after each item; per-item errors are counted but never abort the batch.
  • Replaces the notice with a completion summary on finish.

Build (webpack.config.js):

  • Adds experiments/alt-text-generation-bulk entry point.

Tests (tests/Integration/Includes/Experiments/Alt_Text_Generation/Alt_Text_GenerationTest.php):

  • 5 new integration tests covering: bulk action registration (enabled/disabled), redirect URL query args for image attachments, non-image filtering, and unrelated action passthrough.

Use of AI Tools

Implementation was planned with assistance from Claude Code (Anthropic). All code was reviewed, tested, and validated.

Testing Instructions

  1. Activate the plugin locally and ensure the Alt Text Generation experiment is enabled.
  2. Upload at least 2–3 images to the Media Library.
  3. Switch to List View in the Media Library (upload.php).
  4. Select 2 or more images using the checkboxes.
  5. Open the Bulk actions dropdown — verify "Generate Alt Text" appears.
  6. Select it and click Apply.
  7. Confirm the page redirects back to upload.php and a progress notice appears: "Generating alt text: 0 / N…".
  8. Watch the counter increment as each image is processed.
  9. On completion, verify the notice shows a summary: "Alt text generated for all N images.".
  10. Open each processed image's Edit Media screen and confirm the Alt Text field is populated.

Testing Instructions for Keyboard

  1. Tab to the Media Library list view and use Space to check image rows.
  2. Tab to the Bulk actions dropdown and use arrow keys to select "Generate Alt Text".
  3. Tab to the Apply button and press Enter.
  4. Verify the progress notice is injected and focusable; the dismiss button (×) is reachable by keyboard.

Screenshots or screencast

Screen.Recording.2026-03-20.at.10.59.33.PM.mov
Open WordPress Playground Preview

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.82%. Comparing base (e511ceb) to head (6a00850).
⚠️ Report is 20 commits behind head on develop.

Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #330      +/-   ##
=============================================
+ Coverage      64.33%   65.82%   +1.48%     
- Complexity       753      763      +10     
=============================================
  Files             53       53              
  Lines           3827     3859      +32     
=============================================
+ Hits            2462     2540      +78     
+ Misses          1365     1319      -46     
Flag Coverage Δ
unit 65.82% <100.00%> (+1.48%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zeus2611 zeus2611 marked this pull request as ready for review March 20, 2026 18:58
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 20, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: zeus2611 <n1schay@git.wordpress.org>
Co-authored-by: jeffpaul <jeffpaul@git.wordpress.org>
Co-authored-by: dkotter <dkotter@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@jeffpaul jeffpaul added this to the 0.7.0 milestone Mar 23, 2026
@jeffpaul jeffpaul requested review from dkotter and jeffpaul March 23, 2026 20:14
@jeffpaul
Copy link
Copy Markdown
Member

Looks like there must be a character limit being enforced somewhere as this one (of two sample images used for testing) had an ellipses (...) added to the end of the Alt Text field:

Screenshot 2026-03-23 at 3 17 06 PM

I would say we either should render the entire alt text provided or enforce a character limit in the alt text generation prompt?

@zeus2611
Copy link
Copy Markdown
Contributor Author

Thanks for catching this @jeffpaul — the truncation comes from a hard limit in the Ability class (Alt_Text_Generation.php:207-209).

This affects all alt text generation (individual + bulk). The ... gets stored literally in the alt text field, which means screen readers will read it aloud as "dot dot dot" — cutting off meaning and hurting the accessibility we're trying to improve.

The system instruction already soft-limits output to 125 characters ("when possible"). Per WCAG image alt text guidelines, alt text should be "succinct", not artificially truncated. A full 150-character description serves users better than one cut at 122 characters with ... appended.

Should we remove the hard truncation and rely on the prompt guidance?

@dkotter
Copy link
Copy Markdown
Collaborator

dkotter commented Mar 25, 2026

Thanks for catching this @jeffpaul — the truncation comes from a hard limit in the Ability class (Alt_Text_Generation.php:207-209).

This affects all alt text generation (individual + bulk). The ... gets stored literally in the alt text field, which means screen readers will read it aloud as "dot dot dot" — cutting off meaning and hurting the accessibility we're trying to improve.

The system instruction already soft-limits output to 125 characters ("when possible"). Per WCAG image alt text guidelines, alt text should be "succinct", not artificially truncated. A full 150-character description serves users better than one cut at 122 characters with ... appended.

Should we remove the hard truncation and rely on the prompt guidance?

Yeah, this limit has been in place since the original PR (see here). I'm not sure on the "why" here though I'd suggest we just remove that limit. I think it's fine to suggest a limit in our system instructions (though LLM's are notorious for not following length requirements) but I don't think we should truncate ourselves

@zeus2611
Copy link
Copy Markdown
Contributor Author

Removed the hard 125-character truncation in includes/Abilities/Image/Alt_Text_Generation.php per @dkotter's feedback. The system instruction's soft limit ("Keep it under 125 characters when possible") remains as guidance for the AI. No tests were affected — no existing tests asserted truncation behavior.

Copy link
Copy Markdown
Collaborator

@dkotter dkotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and overall works good, left a handful of comments. Also would be great to get E2E tests here to cover these changes

@jeffpaul jeffpaul requested a review from dkotter April 8, 2026 13:24
jeffpaul
jeffpaul previously approved these changes Apr 8, 2026
Copy link
Copy Markdown
Collaborator

@dkotter dkotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few more comments and would still want some E2E tests here before we merge this

@zeus2611
Copy link
Copy Markdown
Contributor Author

zeus2611 commented Apr 8, 2026

Added E2E tests in tests/e2e/specs/experiments/alt-text-generation-bulk.spec.js covering: bulk action visibility in list view, generation flow with progress notice, URL cleanup after completion, and hidden action when experiment is disabled.

@jeffpaul jeffpaul requested a review from dkotter April 8, 2026 19:42
@jeffpaul jeffpaul mentioned this pull request Apr 8, 2026
31 tasks
zeus2611 added 2 commits April 9, 2026 01:42
… details

tests: fix script path in Alt_Text_GenerationTest and update experiment name in E2E tests
dkotter
dkotter previously approved these changes Apr 8, 2026
@dkotter
Copy link
Copy Markdown
Collaborator

dkotter commented Apr 8, 2026

Looks like some new failing E2E tests here (outside of the known failures we have that are being fixed elsewhere). I think the issue here is we toggle over to the list media view and then we don't toggle back to the grid view, so those tests are failing. I can take a look once we have the existing tests fixed up in a separate PR as it's hard to parse through that right now

@zeus2611
Copy link
Copy Markdown
Contributor Author

zeus2611 commented Apr 9, 2026

@dkotter All CI tests have passed successfully. I believe this is ready to be merged.

@dkotter dkotter merged commit 4f7a3ba into WordPress:develop Apr 9, 2026
18 checks passed
@zeus2611 zeus2611 deleted the feature/bulk-alt-text-generation branch April 9, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add generated alt text in Edit Media and bulk generate option in Media Library

3 participants