-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use official pug-lint to lint pug files (#65)
* WIP: Make sure to pass items to puglint * Group test cases instead of defining just valid/invalid cases * Make more complicated tests for pug-lint * Make sure pug-lint works well with indentation * Improve integration with Attribute Brackets rule * Make sure we work properly with one-line statements * Make sure we describe the rule for others * Make sure we mention pug-lint in main configuration
- Loading branch information
Showing
10 changed files
with
930 additions
and
355 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Inherit pug-lint to validate pug (experimental) | ||
|
||
This rule applies pug-lint to pug templates in js. | ||
|
||
[See pug-lint project](https://github.com/pugjs/pug-lint) | ||
|
||
## Rule Details | ||
|
||
The following patterns are considered warnings: | ||
|
||
```jsx | ||
/*eslint react-pug/pug-lint: ["error", { "requireSpaceAfterCodeOperator": true }]*/ | ||
pug`div=greeting` | ||
``` | ||
|
||
```jsx | ||
/*eslint react-pug/pug-lint: ["error", { "disallowTrailingSpaces": true }]*/ | ||
pug`div: img() ` | ||
``` | ||
|
||
The following patterns are **not** considered warnings: | ||
|
||
```jsx | ||
/*eslint react-pug/pug-lint: ["error", { "requireSpaceAfterCodeOperator": true }]*/ | ||
pug`div= greeting` | ||
``` | ||
|
||
```jsx | ||
/*eslint react-pug/pug-lint: ["error", { "disallowTrailingSpaces": true }]*/ | ||
pug`div: img()` | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/** | ||
* @fileoverview Inherit pug-lint to validate pug | ||
* @author Eugene Zhlobo | ||
*/ | ||
|
||
const Linter = require('pug-lint') | ||
const common = require('common-prefix') | ||
|
||
const { isReactPugReference, buildLocation, docsUrl } = require('../util/eslint') | ||
const getTemplate = require('../util/getTemplate') | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
const buildMessage = actual => ( | ||
`Invalid indentation, found "${actual}" spaces` | ||
) | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Inherit pug-lint to validate pug (experimental)', | ||
category: 'Stylistic Issues', | ||
recommended: false, | ||
url: docsUrl('pug-lint'), | ||
}, | ||
schema: [ | ||
{ | ||
type: 'object', | ||
}, | ||
], | ||
}, | ||
|
||
create: function (context) { | ||
return { | ||
TaggedTemplateExpression: function (node) { | ||
if (isReactPugReference(node)) { | ||
const template = getTemplate(node) | ||
const lines = template.split('\n') | ||
|
||
const linter = new Linter() | ||
|
||
linter.configure(context.options[0]) | ||
|
||
const firstTokenInLine = context | ||
.getSourceCode() | ||
.getTokensBefore(node, { | ||
filter: token => token.loc.end.line === node.loc.start.line, | ||
})[0] | ||
|
||
const minimalIndent = firstTokenInLine | ||
? firstTokenInLine.loc.start.column | ||
: node.loc.start.column | ||
|
||
const desiredIndent = lines.length > 1 | ||
? minimalIndent + 2 | ||
: 0 | ||
|
||
const amountOfUselessSpaces = common(lines.filter(item => item.trim() !== '')) | ||
.replace(/^(\s*).*/, '$1') | ||
.length | ||
|
||
if (amountOfUselessSpaces > 0 && amountOfUselessSpaces < desiredIndent) { | ||
context.report({ | ||
node, | ||
message: buildMessage(amountOfUselessSpaces), | ||
loc: buildLocation( | ||
[(node.loc.start.line + 1), 0], | ||
[(node.loc.start.line + 1), amountOfUselessSpaces], | ||
), | ||
}) | ||
|
||
return null | ||
} | ||
|
||
// We need to pass the template without not valuable spaces in the | ||
// beginning of each line | ||
const preparedTemplate = lines | ||
.map(item => item.slice(desiredIndent)) | ||
.join('\n') | ||
|
||
const result = linter.checkString(preparedTemplate, 'testfile') | ||
|
||
if (result.length) { | ||
result.forEach((error) => { | ||
const delta = error.line === 1 | ||
// When template starts plus backtick | ||
? node.quasi.quasis[0].loc.start.column + 1 | ||
: desiredIndent - 1 | ||
|
||
let columnStart = error.column + delta | ||
let columnEnd = error.column + delta | ||
let message = error.msg | ||
|
||
if (error.msg === 'Invalid indentation') { | ||
columnStart = 0 | ||
columnEnd = preparedTemplate.split('\n')[error.line - 1].replace(/^(\s*).*/, '$1').length + desiredIndent | ||
message = buildMessage(columnEnd) | ||
} | ||
|
||
context.report({ | ||
node, | ||
message, | ||
loc: buildLocation( | ||
[(node.loc.start.line + error.line) - 1, columnStart], | ||
[(node.loc.start.line + error.line) - 1, columnEnd], | ||
), | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
return null | ||
}, | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const extractCase = type => item => ({ | ||
options: item.options || [], | ||
...item[type], | ||
}) | ||
|
||
const extractCases = type => (items) => { | ||
if (items.some(item => item.only)) { | ||
return items.filter(item => item.only).map(extractCase(type)) | ||
} | ||
|
||
return items.map(extractCase(type)) | ||
} | ||
|
||
module.exports = function (cases) { | ||
return { | ||
valid: extractCases('valid')(cases), | ||
invalid: extractCases('invalid')(cases), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.