1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 | const docsUrl = require('../util/docsUrl');
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | module.exports = {
|
15 | meta: {
|
16 | docs: {
|
17 | description: 'Ensure proper position of the first property in JSX',
|
18 | category: 'Stylistic Issues',
|
19 | recommended: false,
|
20 | url: docsUrl('jsx-first-prop-new-line')
|
21 | },
|
22 | fixable: 'code',
|
23 |
|
24 | schema: [{
|
25 | enum: ['always', 'never', 'multiline', 'multiline-multiprop']
|
26 | }]
|
27 | },
|
28 |
|
29 | create(context) {
|
30 | const configuration = context.options[0] || 'multiline-multiprop';
|
31 |
|
32 | function isMultilineJSX(jsxNode) {
|
33 | return jsxNode.loc.start.line < jsxNode.loc.end.line;
|
34 | }
|
35 |
|
36 | return {
|
37 | JSXOpeningElement(node) {
|
38 | if (
|
39 | (configuration === 'multiline' && isMultilineJSX(node))
|
40 | || (configuration === 'multiline-multiprop' && isMultilineJSX(node) && node.attributes.length > 1)
|
41 | || (configuration === 'always')
|
42 | ) {
|
43 | node.attributes.some((decl) => {
|
44 | if (decl.loc.start.line === node.loc.start.line) {
|
45 | context.report({
|
46 | node: decl,
|
47 | message: 'Property should be placed on a new line',
|
48 | fix(fixer) {
|
49 | return fixer.replaceTextRange([node.name.range[1], decl.range[0]], '\n');
|
50 | }
|
51 | });
|
52 | }
|
53 | return true;
|
54 | });
|
55 | } else if (configuration === 'never' && node.attributes.length > 0) {
|
56 | const firstNode = node.attributes[0];
|
57 | if (node.loc.start.line < firstNode.loc.start.line) {
|
58 | context.report({
|
59 | node: firstNode,
|
60 | message: 'Property should be placed on the same line as the component declaration',
|
61 | fix(fixer) {
|
62 | return fixer.replaceTextRange([node.name.range[1], firstNode.range[0]], ' ');
|
63 | }
|
64 | });
|
65 | }
|
66 | }
|
67 | }
|
68 | };
|
69 | }
|
70 | };
|