Skip to content

Commit

Permalink
Add rule "indent" to enforce consistent indentation (#39)
Browse files Browse the repository at this point in the history
It always requires 2-space indentation.

Request: #35
  • Loading branch information
ezhlobo authored Aug 29, 2018
1 parent 8f3e197 commit ad529e9
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Then configure the rules you want to use under the rules section.

## List of supported rules

* [`react-pug/indent`](./docs/rules/indent.md): Enforce consistent indentation
* [`react-pug/no-broken-template`](./docs/rules/no-broken-template.md): Disallow broken template
* [`react-pug/no-interpolation`](./docs/rules/no-interpolation.md): Disallow JavaScript interpolation
* [`react-pug/no-undef`](./docs/rules/no-undef.md): Disallow undeclared variables in Pug
Expand Down
39 changes: 39 additions & 0 deletions docs/rules/indent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Enforce consistent indentation (react-pug/indent)

This helps to be consistent with using indentation across the codebase.

Basically it requires 2 spaces always.

## Rule Details

The following patterns are considered warnings:

```jsx
pug`
div
`
```

```jsx
pug`
div
div
`
```

The following patterns are **not** considered warnings:

```jsx
pug`div= 'Hello'`
```

```jsx
pug`
div
div
`
```

## When Not To Use It

If you are not using Pug then you can disable this rule.
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

/* eslint-disable global-require */
const allRules = {
indent: require('./lib/rules/indent'),
'no-broken-template': require('./lib/rules/no-broken-template'),
'no-interpolation': require('./lib/rules/no-interpolation'),
'no-undef': require('./lib/rules/no-undef'),
Expand All @@ -21,6 +22,7 @@ module.exports = {
pug: true,
},
rules: {
'react-pug/indent': 2,
'react-pug/no-broken-template': 2,
'react-pug/no-undef': 2,
'react-pug/no-interpolation': 2,
Expand Down
82 changes: 82 additions & 0 deletions lib/rules/indent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* @fileoverview Enforce consistent indentation
* @author Eugene Zhlobo
*/

const { isReactPugReference, buildLocation, docsUrl } = require('../util/eslint')
const getTemplate = require('../util/getTemplate')
const getTokens = require('../util/getTokens')

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

const buildMessage = (expected, actual) => (
`Expected indentation of ${expected} spaces but found ${actual}`
)

module.exports = {
meta: {
docs: {
description: 'Enforce consistent indentation',
category: 'Stylistic Issues',
recommended: true,
url: docsUrl('indent'),
},
schema: [],
},

create: function (context) {
const STEP = 2

return {
TaggedTemplateExpression: function (node) {
if (isReactPugReference(node)) {
if (node.loc.end.line === node.loc.start.line) {
return false
}

const wrongIndent = []

const template = getTemplate(node)
const tokens = getTokens(template)

const minimalIndent = node.loc.start.column

let currentIndent = 0
tokens.forEach((token, index) => {
if (token.type === 'indent' || index === 0) {
currentIndent += 1

const actual = token.loc.end.column - 1
const expected = minimalIndent + currentIndent * STEP

if (actual !== expected) {
wrongIndent.push({
line: token.loc.start.line,
actual,
expected,
})
}
} else if (token.type === 'outdent') {
currentIndent -= 1
}
})

wrongIndent.forEach((item) => {
context.report({
node,
loc: buildLocation(
[item.line + node.loc.start.line - 1, 0],
[item.line + node.loc.start.line - 1, item.actual],
),
message: buildMessage(item.expected, item.actual),
})
})
}

return false
},
}
},
}
166 changes: 166 additions & 0 deletions tests/lib/rules/indent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/**
* @fileoverview Tests for indent
* @author Eugene Zhlobo
*/

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const eslint = require('eslint')

const { RuleTester } = eslint

const rule = require('../../../lib/rules/indent')

const parserOptions = {
ecmaVersion: 8,
sourceType: 'module',
}

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({ parserOptions })

const buildMessage = (expected, actual) => (
`Expected indentation of ${expected} spaces but found ${actual}`
)

ruleTester.run('rule "indent"', rule, {
valid: [
{ code: 'pug`div`' },
{
code: `
pug\`
div
div: div
div
div
\`
`,
},
],
invalid: [
{
code: `
pug\`
test
\`
`,
errors: [{
message: buildMessage(10, 0),
line: 3,
column: 1,
endLine: 3,
endColumn: 1,
}],
},
{
code: `
pug\`
test
\`
`,
errors: [{
message: buildMessage(10, 9),
line: 3,
column: 1,
endLine: 3,
endColumn: 10,
}],
},
{
code: `
pug\`
div
\`
`,
errors: [{
message: buildMessage(10, 11),
line: 3,
column: 1,
endLine: 3,
endColumn: 12,
}],
},
{
code: `
pug\`
div
\`
`,
errors: [{
message: buildMessage(12, 13),
line: 3,
column: 1,
endLine: 3,
endColumn: 14,
}],
},
{
code: `
pug\`
div
div
div
div
div
\`
`,
errors: [{
message: buildMessage(12, 11),
line: 7,
column: 1,
endLine: 7,
endColumn: 12,
}],
},
{
code: `
pug\`
div
div
div(incorrect)
p
div(incorrect)
\`
`,
errors: [{
message: buildMessage(14, 13),
line: 5,
column: 1,
endLine: 5,
endColumn: 14,
}, {
message: buildMessage(16, 14),
line: 6,
column: 1,
endLine: 6,
endColumn: 15,
}],
},
{
code: `
pug\`
div
div
\`
`,
errors: [{
message: buildMessage(10, 12),
line: 3,
column: 1,
endLine: 3,
endColumn: 13,
}, {
message: buildMessage(12, 16),
line: 4,
column: 1,
endLine: 4,
endColumn: 17,
}],
},
],
})
14 changes: 14 additions & 0 deletions tests/lib/rules/no-broken-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,19 @@ ruleTester.run('rule "no-broken-template"', rule, {
message: 'Pug can\'t parse this template',
}],
},
{
code: `pug\`
div
div
div
\``,
errors: [{
line: 4,
column: 10,
endLine: 4,
endColumn: 13,
message: 'Pug can\'t parse this template',
}],
},
],
})

0 comments on commit ad529e9

Please sign in to comment.