Repository: ember-template-lint/ember-template-lint
Pull request #672 (2019-03-12 20:48:22)

feat: add `allowDynamicStyles` option to `no-inline-styles` lint rule
Dynamic values for inline styles often serve a useful purpose, such as in these examples (taken from the [style-concatenation](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/style-concatenation.md) rule documentation examples):

```
<div style={{html-safe (concat "background-image: url(" url ")")}}>
```

```
<div style={{background-image url}}>
```

```
<div style={{background-color myBackgroundColor}}></div>
```

Note that the similar [no-inline-styles](https://github.com/Intellicode/eslint-plugin-react-native/blob/master/docs/rules/no-inline-styles.md) lint rule for React has the default behavior of only disallowing inline styles with literal values while allowing those with dynamic values.


Patch:
diff --git a/docs/rule/no-inline-styles.md b/docs/rule/no-inline-styles.md
index 60a89454..5c36e0c2 100644
--- a/docs/rule/no-inline-styles.md
+++ b/docs/rule/no-inline-styles.md
@@ -14,6 +14,19 @@ This rule **allows** the following:
 <div class="wide-element"></div>
 ```
 
+```hbs
+{{! only allowed when `allowDynamicStyles` is enabled }}
+<div style={{html-safe (concat "background-image: url(" url ")")}}></div>
+```
+
+### Configuration
+
+ The following values are valid configuration:
+
+  * boolean - `true` to enable / `false` to disable
+  * object -- An object with the following keys:
+    * `allowDynamicStyles` -- Whether dynamically-generated inline styles should be allowed (defaults to `false`)
+
 ### Related Rules
 
 * [style-concatenation](style-concatenation.md)
diff --git a/lib/rules/lint-no-inline-styles.js b/lib/rules/lint-no-inline-styles.js
index 021b1c59..22d3d876 100644
--- a/lib/rules/lint-no-inline-styles.js
+++ b/lib/rules/lint-no-inline-styles.js
@@ -2,6 +2,7 @@
 
 const AstNodeInfo = require('../helpers/ast-node-info');
 const Rule = require('./base');
+const createErrorMessage = require('../helpers/create-error-message');
 
 /**
  Disallow usage of elements with inline styles
@@ -18,19 +19,54 @@ const Rule = require('./base');
  <div style="display:inline-block"></div>
  ```
  */
+
+const DEFAULT_CONFIG = { allowDynamicStyles: false };
+
 module.exports = class InlineStyles extends Rule {
+  parseConfig(config) {
+    let configType = typeof config;
+
+    switch (configType) {
+      case 'boolean':
+        return config ? DEFAULT_CONFIG : false;
+      case 'object':
+        return { allowDynamicStyles: config.allowDynamicStyles };
+      case 'undefined':
+        return false;
+    }
+
+    let errorMessage = createErrorMessage(
+      this.ruleName,
+      [
+        '  * boolean - `true` to enable / `false` to disable',
+        '  * object -- An object with the following keys:',
+        '    * `allowDynamicStyles` -- Whether dynamically-generated inline styles should be allowed (defaults to `false`)',
+      ],
+      config
+    );
+
+    throw new Error(errorMessage);
+  }
+
   visitor() {
     return {
       ElementNode(node) {
-        let style = AstNodeInfo.findAttribute(node, 'style');
-        if (style) {
-          this.log({
-            message: 'elements cannot have inline styles',
-            line: style.loc && style.loc.start.line,
-            column: style.loc && style.loc.start.column,
-            source: this.sourceForNode(style),
-          });
+        const style = AstNodeInfo.findAttribute(node, 'style');
+        if (!style) {
+          return;
         }
+
+        const hasDynamicStyle = AstNodeInfo.isMustacheStatement(style.value);
+        if (this.config.allowDynamicStyles && hasDynamicStyle) {
+          return;
+        }
+
+        this.log({
+          message: 'elements cannot have inline styles',
+          line: style.loc && style.loc.start.line,
+          column: style.loc && style.loc.start.column,
+          source: this.sourceForNode(style),
+        });
       },
     };
   }


Test patch:
diff --git a/test/unit/rules/lint-no-inline-styles-test.js b/test/unit/rules/lint-no-inline-styles-test.js
index 30f35e73..323890c2 100644
--- a/test/unit/rules/lint-no-inline-styles-test.js
+++ b/test/unit/rules/lint-no-inline-styles-test.js
@@ -21,7 +21,15 @@ generateRuleTests({
 
   config: true,
 
-  good: ['<div></div>', '<span></span>', '<ul class="dummy"></ul>'],
+  good: [
+    '<div></div>',
+    '<span></span>',
+    '<ul class="dummy"></ul>',
+    {
+      config: { allowDynamicStyles: true },
+      template: '<div style={{html-safe (concat "background-image: url(" url ")")}}></div>',
+    },
+  ],
 
   bad: [
     'style="width: 100px"',