Skip to content

Commit 1430c61

Browse files
Merge pull request #2442 from NullVoxPopuli/nvp/template-lint-extract-rule-template-no-inline-styles
Extract rule: template-no-inline-styles
2 parents a77ab85 + 125fccb commit 1430c61

File tree

4 files changed

+113
-0
lines changed

4 files changed

+113
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ rules in templates can be disabled with eslint directives with mustache or html
203203
| [template-no-chained-this](docs/rules/template-no-chained-this.md) | disallow redundant `this.this` in templates | | 🔧 | |
204204
| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
205205
| [template-no-element-event-actions](docs/rules/template-no-element-event-actions.md) | disallow element event actions (use {{on}} modifier instead) | | | |
206+
| [template-no-inline-styles](docs/rules/template-no-inline-styles.md) | disallow inline styles | | | |
206207
| [template-no-input-placeholder](docs/rules/template-no-input-placeholder.md) | disallow placeholder attribute on input elements | | | |
207208
| [template-no-input-tagname](docs/rules/template-no-input-tagname.md) | disallow tagName attribute on {{input}} helper | | | |
208209
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ember/template-no-inline-styles
2+
3+
<!-- end auto-generated rule header -->
4+
5+
Inline styles are not the best practice because they are hard to maintain and usually make the overall size of the project bigger. This rule forbids inline styles. Use CSS classes instead.
6+
7+
## Examples
8+
9+
This rule **forbids** the following:
10+
11+
```gjs
12+
<template><div style='width:900px'></div></template>
13+
```
14+
15+
This rule **allows** the following:
16+
17+
```gjs
18+
<template><div class='wide-element'></div></template>
19+
```
20+
21+
```gjs
22+
<template>
23+
{{! allowed when `allowDynamicStyles` is enabled }}
24+
<div style={{html-safe (concat 'background-image: url(' url ')')}}></div>
25+
</template>
26+
```
27+
28+
## Options
29+
30+
| Name | Type | Default | Description |
31+
| -------------------- | --------- | ------- | ------------------------------------------------------------------------------------- |
32+
| `allowDynamicStyles` | `boolean` | `true` | When `true`, allows dynamic style values (e.g. `style={{...}}` or `style="{{...}}"`). |
33+
34+
## Related Rules
35+
36+
- [style-concatenation](style-concatenation.md)
37+
38+
## References
39+
40+
- [Deprecations/binding style attributes](https://emberjs.com/deprecations/v1.x/#toc_binding-style-attributes)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'suggestion',
5+
docs: {
6+
description: 'disallow inline styles',
7+
category: 'Best Practices',
8+
recommendedGjs: false,
9+
recommendedGts: false,
10+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-inline-styles.md',
11+
},
12+
schema: [
13+
{
14+
type: 'object',
15+
properties: {
16+
allowDynamicStyles: { type: 'boolean' },
17+
},
18+
additionalProperties: false,
19+
},
20+
],
21+
messages: { noInlineStyles: 'Inline styles are not allowed' },
22+
},
23+
create(context) {
24+
const options = context.options[0] || {};
25+
const allowDynamicStyles =
26+
options.allowDynamicStyles === undefined ? true : options.allowDynamicStyles;
27+
28+
return {
29+
GlimmerElementNode(node) {
30+
const styleAttr = node.attributes?.find((a) => a.name === 'style');
31+
if (!styleAttr) {
32+
return;
33+
}
34+
35+
// If allowDynamicStyles is true, skip dynamic style values (MustacheStatement/ConcatStatement)
36+
if (allowDynamicStyles) {
37+
const valType = styleAttr.value?.type;
38+
if (valType === 'GlimmerMustacheStatement' || valType === 'GlimmerConcatStatement') {
39+
return;
40+
}
41+
}
42+
43+
context.report({ node: styleAttr, messageId: 'noInlineStyles' });
44+
},
45+
};
46+
},
47+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const rule = require('../../../lib/rules/template-no-inline-styles');
2+
const RuleTester = require('eslint').RuleTester;
3+
4+
const ruleTester = new RuleTester({
5+
parser: require.resolve('ember-eslint-parser'),
6+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
7+
});
8+
ruleTester.run('template-no-inline-styles', rule, {
9+
valid: [
10+
'<template><div class="foo"></div></template>',
11+
// Test cases ported from ember-template-lint
12+
'<template><div></div></template>',
13+
'<template><span></span></template>',
14+
'<template><ul class="dummy"></ul></template>',
15+
'<template><div style={{foo}}></div></template>',
16+
'<template><div style={{html-safe (concat "background-image: url(" url ")")}}></div></template>',
17+
],
18+
invalid: [
19+
{
20+
code: '<template><div style="color: red"></div></template>',
21+
output: null,
22+
errors: [{ messageId: 'noInlineStyles' }],
23+
},
24+
],
25+
});

0 commit comments

Comments
 (0)