Skip to content

fix(linter/aria-proptypes): allow template literals with expressions for string-type ARIA props#17460

Merged
connorshea merged 6 commits intooxc-project:mainfrom
jokull:fix/aria-proptypes-template-literals
Jan 1, 2026
Merged

fix(linter/aria-proptypes): allow template literals with expressions for string-type ARIA props#17460
connorshea merged 6 commits intooxc-project:mainfrom
jokull:fix/aria-proptypes-template-literals

Conversation

@jokull
Copy link
Contributor

@jokull jokull commented Dec 29, 2025

Summary

Fixes a false positive in jsx_a11y/aria-proptypes where template literals with expressions (e.g., `Hello ${name}`) were incorrectly flagged as invalid for string-type ARIA props like aria-label.

The Problem

<div aria-label={`Hello ${name}`} />  // ❌ Was incorrectly flagged as invalid

For aria-label (and other string-type ARIA props), any string value is valid. Template literals with expressions always produce strings at runtime, so they should be allowed.

Copilot AI review requested due to automatic review settings December 29, 2025 12:19
@jokull jokull requested a review from camc314 as a code owner December 29, 2025 12:19
@github-actions github-actions bot added A-linter Area - Linter C-bug Category - Bug labels Dec 29, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a false positive in the jsx_a11y/aria-proptypes linter rule where template literals containing expressions (e.g., `Hello ${name}`) were incorrectly flagged as invalid ARIA property values.

Key Changes:

  • Modified is_target_literal_value to only validate template literals without expressions (single quasi templates)
  • Template literals with expressions are now treated like variables and skipped during static validation
  • Moved test cases from fail to pass to reflect the corrected behavior

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jokull jokull force-pushed the fix/aria-proptypes-template-literals branch from 07fb8fc to bf41daf Compare December 29, 2025 12:21
…for string-type ARIA props

Template literals with expressions (e.g., `aria-label={`Hello ${name}`}`) were
incorrectly flagged as invalid because the linter could not extract their value.

For string-type ARIA props, template literals with expressions are now allowed
since they always produce strings at runtime.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jokull jokull force-pushed the fix/aria-proptypes-template-literals branch from bf41daf to 4818575 Compare December 29, 2025 15:17
@jokull
Copy link
Contributor Author

jokull commented Dec 29, 2025

Thanks - changed the scope of the change, should be isolated to aria-label case now. Thank you!

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 30, 2025

CodSpeed Performance Report

Merging #17460 will not alter performance

Comparing jokull:fix/aria-proptypes-template-literals (a4d5ecb) with main (bb2e8e4)

Summary

✅ 4 untouched
⏩ 41 skipped1

Footnotes

  1. 41 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@connorshea
Copy link
Member

Should note that #17465 also needs to be fixed (in regards to aria-labelledby). Can be done in this PR, or a separate PR if we prefer to keep this one simple.

@connorshea
Copy link
Member

connorshea commented Dec 30, 2025

A few extra test cases to ensure labelledby works, currently these fail if added:

        // Ensure that template literals with expressions are allowed.
        r#"<div aria-labelledby={`${id}-label`} />"#,
        r#"<div aria-labelledby={`${id}`} />"#,
        r#"<div aria-labelledby={`${id}-label ${id}-help-text`} />"#,

Will need to update the code accordingly, but again I'm fine with merging this as-is (pending a review by cam), and deferring the change for labelledby to a subsequent PR.

Should maybe add the exact same cases for describedby, flowto, etc. by just copy-pasting the above 3 tests and replacing labelledby with the other idlist aria props.

@connorshea
Copy link
Member

I've updated the code to work for the labelledby/describedby aria props as well, so this should be good to go now :)

To ensure this doesn't regress.
Copy link
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

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

Thank you!

@connorshea connorshea merged commit be39906 into oxc-project:main Jan 1, 2026
20 checks passed
graphite-app bot pushed a commit that referenced this pull request Jan 5, 2026
# Oxlint
### 💥 BREAKING CHANGES

- f7da875 oxlint: [**BREAKING**] Remove oxc_language_server binary (#17457) (Boshen)

### 🚀 Features

- 659c23e linter: Init note field boilerplate  (#17589) (Shrey Sudhir)
- 6870b64 parser: Add TS1363 error code (#17609) (Sysix)
- 6154c8c linter/eslint-plugin-vitest: Implemented vitest/warn-todo rule (#17228) (Said Atrahouch)
- 0043cd6 linter/eslint-plugin-vitest: Implement consistent-vitest-vi rule (#17389) (Said Atrahouch)
- a6d773d linter: Add full TS support to eslint/no-useless-constructor (#17592) (camc314)
- f02c0e7 linter/eslint: Implement complexity (#17569) (Nguyen Tran)
- bc7aae7 linter/no-unused-vars: Add fixer to remove unused catch bindings (#17567) (Don Isaac)
- 9e8ec78 linter/only-throw-error rule: Add `allowRethrowing` option for  (#17554) (camc314)
- b67e819 linter: Add fixer for `unicorn/prefer-response-static-json` rule (#17559) (Mikhail Baev)
- 44b0361 linter/vue: Implement no-this-in-before-route-enter (#17525) (yefan)
- ee34716 linter/react: Implement no-will-update-set-state (#17530) (Kenzo Wada)
- 3088e1d linter/react: Implement no-this-in-sfc (#17535) (Kenzo Wada)
- 29a2868 linter/jsx-a11y: Implement no-static-element-interactions (#17538) (Kenzo Wada)
- eadf057 linter: Enable tsconfig auto discovery by default (#17489) (Boshen)
- 12a7d6e website_linter: Add a count of rules with fixes available to rules table. (#17476) (Connor Shea)

### 🐛 Bug Fixes

- a702f13 oxlint/lsp: Correct position for "disable for this file" with shebang (#17613) (Sysix)
- 19fdfb6 linter: Panic in `sort-keys` rule with Unicode numeric characters (#17629) (Adel Rodríguez)
- 2e8f469 vscode: Search for `node_modules/.bin/oxlint.exe` too (bun setup) (#17597) (Sysix)
- be39906 linter/aria-proptypes: Allow template literals with expressions for string-type ARIA props (#17460) (Jökull Sólberg Auðunsson)
- 529901c linter: Include JS plugin rules when calculating total rule count (#17520) (connorshea)
- 96ef2cc linter: Print total rule # when using a single nested config (#17517) (connorshea)
- 9ad0f29 oxlint: Do not enable external plugin store when no external linter is passed (#17498) (Sysix)
- 174375d oxfmt,oxlint: Disable mimalloc for 32-bit Arm targets (#17473) (Yaksh Bariya)
- ff70fe9 linter/no-standalone-expect: Allows expect in wrapper functions passed to test blocks (#17427) (Copilot)
- dab232f linter/catch-or-return: Handle arrow functions with implicit returns correctly (#17440) (Copilot)
- a38892a linter: Update no-unnecessary-template-expression docs and test case (#17453) (camc314)

### ⚡ Performance

- 605dbf1 vscode: Restrict searching for oxlint/oxfmt binaries only 3 levels deep + 10s timeout (#17345) (Sysix)

### 📚 Documentation

- 884fb63 linter/react: Improve docs for jsx-curly-brace-presence (#17579) (connorshea)
- 1d3ee07 linter: Improve rule explanation for `vue/no-this-in-before-route-enter`. (#17581) (connorshea)
- 5f189f8 linter/arrow-body-style: Correctly document default mode option (#17566) (Rägnar O'ock)
- bb2e8e4 linter: Add a note to the `typescript/no-var-requires` rule about the missing `allow` option (#17551) (connorshea)
- 655afc1 linter: Improve docs for `import/extensions` and add a few more tests (#17539) (connorshea)
- 7e5fc90 linter: Update list of plugins that are reserved. (#17516) (connorshea)
# Oxfmt
### 💥 BREAKING CHANGES

- f7da875 oxlint: [**BREAKING**] Remove oxc_language_server binary (#17457) (Boshen)

### 🚀 Features

- 8fd4ea9 oxfmt: `options.embeddedLanguageFormatting` is now `"auto"` by default (#17649) (leaysgur)

### 🐛 Bug Fixes

- c9b5d7d formatter/sort_imports: Handle alignable_comment correctly (#17646) (leaysgur)
- 453222d formatter: Missing comment handling for end-of-line comments in member chains (#17659) (Dunqing)
- 0805ff2 formatter: Incorrect inline comment placement in try-catch (#17657) (Dunqing)
- 3a0c782 formatter: Don't move comments into optional call parentheses (#17582) (magic-akari)
- 174375d oxfmt,oxlint: Disable mimalloc for 32-bit Arm targets (#17473) (Yaksh Bariya)

### ⚡ Performance

- abb28dc oxfmt: Turn of pretty print from sort-package-json (#17452) (Boshen)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants