Repository: rwjblue/ember-template-lint
Pull request #110 (2016-08-21 18:17:52)

Add inline-link-to rule
I wanted to get my feet wet with this project and I don't like the inline form of link to so I took a shot at implementing a rule for #60.

Let me know what you think!

rwjblue: This looks great! @nathanhammond and I share your hatred of inline link-to...

My only question is RE: the rule name.  I realize that they are all over the map so far and I should come up with a "rule for the rule names". 

Would this rule may be better as `inline-link-to` (which follows the patter of `triple-curlies` / `bare-strings` / `nested-interactive` / `self-closing-void-elements` and forbids the thing it describes)?
mitchlloyd: "inline-link-to" works for me. Going forward maybe this project could adopt
naming similar to ESLint where rules are generally affirmative "eqeqeq" and
forbidding rules begin with "no".

On Sun, Aug 21, 2016 at 12:01 PM Robert Jackson <notifications@github.com>
wrote:

> This looks great! @nathanhammond <https://github.com/nathanhammond> and I
> share your hatred of inline link-to...
>
> My only question is RE: the rule name. I realize that they are all over
> the map so far and I should come up with a "rule for the rule names".
>
> Would this rule may be better as inline-link-to (which follows the patter
> of triple-curlies / bare-strings / nested-interactive /
> self-closing-void-elements and forbids the thing it describes)?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/rwjblue/ember-template-lint/pull/110#issuecomment-241275158>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAA7QRmIk9ipUOerxQTpb6P0Sik7udhKks5qiKCZgaJpZM4JpWmj>
> .
>

rwjblue: Yeah, I agree
mitchlloyd: Updated. Seems like a good one to squash if this looks good.

Patch:
diff --git a/README.md b/README.md
index 53a86e9..c650324 100644
--- a/README.md
+++ b/README.md
@@ -296,6 +296,32 @@ The following values are valid configuration (same as the `nested-interactive` r
     * `ignoreUsemapAttribute` - When `true` ignores the `usemap` attribute on `img` and `object` elements. Defaults `false`.
     * `additionalInteractiveTags` - An array of element tag names that should also be considered as interactive. Defaults to `[]`.'
 
+#### inline-link-to
+
+Ember's `link-to` component has both an inline form and a block form. This rule forbids the inline form.
+
+Forbidden (inline form):
+
+```hbs
+{{link-to 'Link text' 'routeName' prop1 prop2}}
+```
+
+Allowed (block form):
+
+```hbs
+{{#link-to 'routeName' prop1 prop2}}Link text{{/link-to}}
+```
+
+The block form is a little longer but has advantages over the inline form:
+
+* It maps closer to the use of HTML anchor tags which wrap their inner content.
+* It provides an obvious way for developers to put nested markup and components inside of their link.
+* The block form's argument order is more direct: "link to route". The inline form's argument order is somewhat ambiguous (link text then link target). This is opposite of the order in HTML (`href` then link text).
+
+This rule is configured with one boolean value:
+
+  * boolean -- `true` for enabled / `false` for disabled
+
 ### Deprecations
 
 #### deprecated-each-syntax
diff --git a/lib/rules/index.js b/lib/rules/index.js
index a24bb69..a67c771 100644
--- a/lib/rules/index.js
+++ b/lib/rules/index.js
@@ -9,6 +9,7 @@ module.exports = {
   'triple-curlies': require('./lint-triple-curlies'),
   'self-closing-void-elements': require('./lint-self-closing-void-elements'),
   'nested-interactive': require('./lint-nested-interactive'),
+  'inline-link-to': require('./lint-inline-link-to'),
   'deprecated-each-syntax': require('./deprecations/lint-deprecated-each-syntax'),
   'invalid-interactive': require('./lint-invalid-interactive')
 };
diff --git a/lib/rules/lint-inline-link-to.js b/lib/rules/lint-inline-link-to.js
new file mode 100644
index 0000000..42f8820
--- /dev/null
+++ b/lib/rules/lint-inline-link-to.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var buildPlugin = require('./base');
+var message = 'The inline form of link-to is not allowed. Use the block form instead.';
+
+module.exports = function(addonContext) {
+  var InlineLinkTo = buildPlugin(addonContext, 'inline-link-to');
+
+  InlineLinkTo.prototype.visitors = function() {
+    return {
+      MustacheStatement: function(node) {
+        if (node.path.original === 'link-to') {
+          this.log({
+            message: message,
+            line: node.loc && node.loc.start.line,
+            column: node.loc && node.loc.start.column,
+            source: this.sourceForNode(node)
+          });
+        }
+      }
+    };
+  };
+
+  return InlineLinkTo;
+};
+
+module.exports.message = message;


Test patch:
diff --git a/test/unit/rules/inline-link-to-test.js b/test/unit/rules/inline-link-to-test.js
new file mode 100644
index 0000000..9da87d0
--- /dev/null
+++ b/test/unit/rules/inline-link-to-test.js
@@ -0,0 +1,42 @@
+'use strict';
+
+var generateRuleTests = require('../../helpers/rule-test-harness');
+var message = require('../../../lib/rules/lint-inline-link-to').message;
+
+generateRuleTests({
+  name: 'inline-link-to',
+
+  config: true,
+
+  good: [
+    '{{#link-to \'routeName\' prop}}Link text{{/link-to}}',
+    '{{#link-to \'routeName\'}}Link text{{/link-to}}'
+  ],
+
+  bad: [
+    {
+      template: '{{link-to \'Link text\' \'routeName\'}}',
+
+      result: {
+        rule: 'inline-link-to',
+        message: message,
+        moduleId: 'layout.hbs',
+        source: '{{link-to \'Link text\' \'routeName\'}}',
+        line: 1,
+        column: 0
+      }
+    },
+    {
+      template: '{{link-to \'Link text\' \'routeName\' one two}}',
+
+      result: {
+        rule: 'inline-link-to',
+        message: message,
+        moduleId: 'layout.hbs',
+        source: '{{link-to \'Link text\' \'routeName\' one two}}',
+        line: 1,
+        column: 0
+      }
+    }
+  ]
+});