Repository: rwjblue/ember-template-lint
Pull request #159 (2017-01-10 09:32:42)

Fix indentation check on text nodes after a whitespace eating expression
This is a proposal how to (partially) fix https://github.com/rwjblue/ember-template-lint/issues/91 concerning text nodes after expressions with a tilde.

I added a test that would fail without the changes in this PR. At the same time, however, one of the existing tests got broken:

The following structure was in the "good" samples.
```
{{#if isMorning}}  Good morning
{{else if isAfternoon}}  Good afternoon
{{else}}
  Good night
{{/if}}
```

Is that really correct? It looks weird to me. I removed this test from the good samples and moved a variation of it to the bad samples.

I don't insist on my proposal being correct, please take it as an inspiration for fixing the problem.

Note: I also tried to investigate other cases when there's something else than a text node in this position, however, it looks like the parser eats the white space and reports the element being on a wrong line which is something the linter can hardly do anything about - the fix needs to be done elsewhere. I also noticed that even the ```ember build``` command reports wrong line numbers if there are syntax errors at similar positions - completely unrelated to linting.


Patch:
diff --git a/lib/rules/lint-block-indentation.js b/lib/rules/lint-block-indentation.js
index 2cff284..11adac3 100644
--- a/lib/rules/lint-block-indentation.js
+++ b/lib/rules/lint-block-indentation.js
@@ -206,7 +206,8 @@ module.exports = function(addonContext) {
         continue;
       }
 
-      var childStartColumn;
+      var childStartColumn = child.loc.start.column;
+
       // sanitize text node starting column info
       if (AstNodeInfo.isTextNode(child)) {
         // TextNode's include leading newlines, but those newlines do
@@ -217,15 +218,16 @@ module.exports = function(addonContext) {
         // the TextNode is whitespace only, do nothing
         if (firstNonWhitespace === -1) { continue; }
 
+        // reset the child start column if there's a line break
+        if (/^(\r\n|\n)/.test(child.chars)) { childStartColumn = 0; }
+
+        childStartColumn += firstNonWhitespace;
+
         // detect if the TextNode starts with `{{`, if it does
         // correct for the stripped leading backslash (`\{{foo}}`)
-        if (child.chars.slice(0, 2) === '{{') {
-          childStartColumn = child.loc.start.column - 1;
-        } else {
-          childStartColumn = firstNonWhitespace;
+        if (withoutLeadingNewLines.slice(0, 2) === '{{') {
+          childStartColumn -= 1;
         }
-      } else {
-        childStartColumn = child.loc.start.column;
       }
 
       if (expectedStartColumn !== childStartColumn) {


Test patch:
diff --git a/test/unit/rules/lint-block-indentation-test.js b/test/unit/rules/lint-block-indentation-test.js
index d3fb1cb..125e1ef 100644
--- a/test/unit/rules/lint-block-indentation-test.js
+++ b/test/unit/rules/lint-block-indentation-test.js
@@ -28,13 +28,6 @@ generateRuleTests({
     '\n  {{#each cats as |dog|}}\n  {{/each}}',
     '<div><p>Stuff</p></div>',
     '<div>\n  <p>Stuff Here</p>\n</div>',
-    '{{#if isMorning}}' +
-      '  Good morning\n' +
-      '{{else if isAfternoon}}' +
-      '  Good afternoon\n' +
-      '{{else}}\n' +
-      '  Good night\n' +
-      '{{/if}}',
     '{{#if isMorning}}\n' +
       '  Good morning\n' +
       '{{else foo-bar isAfternoon}}\n' +
@@ -131,6 +124,11 @@ generateRuleTests({
       '  <div></div>',
       '{{~/if~}}'
     ].join('\n'),
+    [
+      '{{#if foo~}}',
+      '  -',
+      '{{/if}}'
+    ].join('\n'),
     [
       '<div class="multi"',
       '     id="lines"></div>'
@@ -393,6 +391,27 @@ generateRuleTests({
         line: 4,
         column: 4
       }
+    },
+
+    {
+      template: [
+        '{{#if isMorning}}' +
+        '  Good morning\n' +
+        '{{else if isAfternoon}}\n' +
+        '  Good afternoon\n' +
+        '{{else}}\n' +
+        '  Good night\n' +
+        '{{/if}}'
+      ].join('\n'),
+
+      result: {
+        rule: 'block-indentation',
+        message: 'Incorrect indentation for `  Good morning\n` beginning at L1:C17. Expected `  Good morning\n` to be at an indentation of 2 but was found at 19.',
+        moduleId: 'layout.hbs',
+        source: '{{#if isMorning}}  Good morning\n{{else if isAfternoon}}\n  Good afternoon\n{{else}}\n  Good night\n{{/if}}',
+        line: 1,
+        column: 17
+      }
     }
   ]
 });