Repository: rwjblue/ember-template-lint
Pull request #302 (2017-10-13 18:18:01)

Top level block indentation
For top level blocks, the starting block helper should be located
at line 1 and column 0.

Closes #299


Patch:
diff --git a/lib/rules/lint-block-indentation.js b/lib/rules/lint-block-indentation.js
index 40bd4e5..e721d1d 100644
--- a/lib/rules/lint-block-indentation.js
+++ b/lib/rules/lint-block-indentation.js
@@ -121,11 +121,38 @@ module.exports = class BlockIndentation extends Rule {
       return;
     }
 
+    this.validateBlockStart(node);
     this.validateBlockElse(node);
     this.validateBlockEnd(node);
     this.validateBlockChildren(node);
   }
 
+  validateBlockStart(node) {
+    if (!this.shouldValidateBlockEnd(node)) {
+      return;
+    }
+
+    let startColumn = node.loc.start.column;
+    let startLine = node.loc.start.line;
+
+    if (startLine === 1 && startColumn !== 0) {
+      let isElementNode = AstNodeInfo.isElementNode(node);
+      let displayName = isElementNode ? node.tag : node.path.original;
+      let startLocation = `L${node.loc.start.line}:C${node.loc.start.column}`;
+      let display = isElementNode ? `<${displayName}>` : `{{#${displayName}}}`;
+
+      let warning = `Incorrect indentation for \`${display}\` beginning at ${startLocation}. ` +
+          `Expected \`${display}\` to be at an indentation of 0, but was found at ${startColumn}.`;
+
+      this.log({
+        message: warning,
+        line: node.loc.start.line,
+        column: node.loc.start.column,
+        source: this.sourceForNode(node)
+      });
+    }
+  }
+
   validateBlockEnd(node) {
     if (!this.shouldValidateBlockEnd(node)) {
       return;


Test patch:
diff --git a/test/unit/rules/lint-block-indentation-test.js b/test/unit/rules/lint-block-indentation-test.js
index 9e465fa..29be09a 100644
--- a/test/unit/rules/lint-block-indentation-test.js
+++ b/test/unit/rules/lint-block-indentation-test.js
@@ -8,6 +8,15 @@ generateRuleTests({
   config: 2,
 
   good: [
+    [
+      '  this is fine'
+    ].join('\n'),
+    [
+      '<h1>Header</h1>',
+      '<div>',
+      '  \\{{example}}',
+      '</div>'
+    ].join('\n'),
     [
       '<div>',
       '  \\{{example}}',
@@ -498,13 +507,22 @@ generateRuleTests({
         '{{/if}}'
       ].join('\n'),
 
-      result: {
-        message: 'Incorrect indentation for `if` beginning at L1:C1. Expected `{{/if}}` ending at L2:C7 to be at an indentation of 1 but was found at 0.',
-        moduleId: 'layout.hbs',
-        source: '{{#if foo}}\n{{/if}}',
-        line: 2,
-        column: 7
-      }
+      results: [
+        {
+          message: 'Incorrect indentation for `{{#if}}` beginning at L1:C1. Expected `{{#if}}` to be at an indentation of 0, but was found at 1.',
+          moduleId: 'layout.hbs',
+          source: '{{#if foo}}\n{{/if}}',
+          line: 1,
+          column: 1
+        },
+        {
+          message: 'Incorrect indentation for `if` beginning at L1:C1. Expected `{{/if}}` ending at L2:C7 to be at an indentation of 1 but was found at 0.',
+          moduleId: 'layout.hbs',
+          source: '{{#if foo}}\n{{/if}}',
+          line: 2,
+          column: 7
+        }
+      ]
     },
     {
       template: [
@@ -569,7 +587,38 @@ generateRuleTests({
           column: 4
         }
       ]
-    }
+    },
+    {
+      template: [
+        '     {{#foo-bar}}',
+        '     {{/foo-bar}}'
+      ].join('\n'),
 
+      results: [
+        {
+          message: 'Incorrect indentation for `{{#foo-bar}}` beginning at L1:C5. Expected `{{#foo-bar}}` to be at an indentation of 0, but was found at 5.',
+          moduleId: 'layout.hbs',
+          source: '{{#foo-bar}}\n     {{/foo-bar}}',
+          line: 1,
+          column: 5
+        }
+      ]
+    },
+    {
+      template: [
+        '  <div>',
+        '  </div>'
+      ].join('\n'),
+
+      results: [
+        {
+          message: 'Incorrect indentation for `<div>` beginning at L1:C2. Expected `<div>` to be at an indentation of 0, but was found at 2.',
+          moduleId: 'layout.hbs',
+          source: '<div>\n  </div>',
+          line: 1,
+          column: 2
+        }
+      ]
+    }
   ]
 });