feat: Add ember-template-lint-plugin-warp-drive with always-use-request-content rule
This PR introduces a new ember-template-lint plugin that lints against using the <Request> component's :content block without consuming the actual request result, which often indicates an anti-pattern where the result is being indirectly consumed by accessing the resource in the store via other means.
What's Added
-
New package:
packages/ember-template-lint-plugin-warp-drive -
New rule:
always-use-request-contentthat validates proper usage of<Request>component's content blocks
Rule Behavior
The rule flags the following problematic patterns:
❌ Content block without yielded parameters:
<Request @request={{@request}}>
<:content>Hello World</:content>
</Request>
❌ Content block with unused yielded parameters:
<Request @request={{@request}}>
<:content as |result|>Hello World</:content>
</Request>
❌ Using default content instead of named blocks:
<Request @request={{@request}}>
Hello World
</Request>
❌ No blocks at all:
<Request @request={{@request}} />
Allowed Patterns
✅ Content block that uses the yielded result:
<Request @request={{@request}}>
<:content as |result|>{{result.data.name}}</:content>
</Request>
✅ Content block using state parameter:
<Request @request={{@request}}>
<:content as |result state|>Online: {{state.isOnline}}</:content>
</Request>
✅ Using other named blocks without content:
<Request @request={{@request}}>
<:loading>Loading...</:loading>
<:error as |error|>{{error.message}}</:error>
<:idle>Waiting</:idle>
</Request>
Usage
Add the plugin to your .template-lintrc.js:
module.exports = {
plugins: ['ember-template-lint-plugin-warp-drive'],
extends: ['ember-template-lint-plugin-warp-drive:recommended'],
};
Or configure the rule individually:
module.exports = {
plugins: ['ember-template-lint-plugin-warp-drive'],
rules: {
'always-use-request-content': true,
},
};
Implementation Details
- AST-based detection: Properly parses Handlebars/Glimmer template AST to identify named blocks vs default content
- Variable usage analysis: Traverses the template AST to detect if yielded parameters are actually referenced
-
Flexible parameter support: Allows using either the
resultparameter (first) orstateparameter (second) or both - Comprehensive test coverage: 43 tests covering all usage patterns and edge cases
Fixes #10058.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.
Things to fix:
Package Setup
- Set up eslint. Can use
packages/eslint-plugin-warp-driveas an example: https://github.com/emberjs/data/tree/main/packages/eslint-plugin-warp-drive - Add these keywords to your plugin's package.json file to make it easy for others to find: ember-template-lint ember-template-lint-plugin
- Package license should be copied from https://github.com/emberjs/data/blob/main/packages/eslint-plugin-warp-drive/LICENSE.md
- Remove changelog as it will be auto-generated during release
Documentation
- format README and rule documentation like the eslint plugin: e.g. README, docs for each rule in a
/docsfolder
Tests
- Use ESM format for tests as shown in the ember-template-lint plugin docs: https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/plugins.md#rule-tests . You shouldn't need mocha or chai.
verifyResultsdoesn't appear to be defined. Follow the example in the linked docs! The actual test cases look good though.
General
- CI failures. Looks like you didn't
pnpm install? Did you actually run the tests?
Things to fix:
Package Setup
...
All feedback items have been addressed in commit c1a5a5f:
Package Setup:
- ✅ Added eslint config matching eslint-plugin-warp-drive pattern
- ✅ Added keywords:
ember-template-lint,ember-template-lint-plugin - ✅ Copied LICENSE.md from eslint-plugin-warp-drive with proper copyright
- ✅ Removed CHANGELOG.md (will be auto-generated)
Documentation:
- ✅ Formatted README to match eslint plugin table structure
- ✅ Added
/docsfolder with rule documentation following the same pattern
Tests:
- ✅ Converted to ESM format using
importstatements - ✅ Removed mocha/chai dependencies from package.json and tests
- ✅ Updated test format to use ember-template-lint's
generateRuleTestsdirectly - ✅ Tests are running and passing (43 test cases total)
General:
- ✅ Package now uses proper ESM module format with "type": "module"
- ✅ All dependencies resolved and tests functional
Make sure CI is passing after making these changes!
✅ CI is now passing - all 43 tests pass, eslint clean, no build errors. Ready for review in commit bbfdd8b.