source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-indent-props.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/**
2 * @fileoverview Validate props indentation in JSX
3 * @author Yannick Croissant
4
5 * This rule has been ported and modified from eslint and nodeca.
6 * @author Vitaly Puzrin
7 * @author Gyandeep Singh
8 * @copyright 2015 Vitaly Puzrin. All rights reserved.
9 * @copyright 2015 Gyandeep Singh. All rights reserved.
10 Copyright (C) 2014 by Vitaly Puzrin
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the 'Software'), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 THE SOFTWARE.
29 */
30
31'use strict';
32
33const repeat = require('string.prototype.repeat');
34
35const astUtil = require('../util/ast');
36const docsUrl = require('../util/docsUrl');
37const getText = require('../util/eslint').getText;
38const reportC = require('../util/report');
39
40// ------------------------------------------------------------------------------
41// Rule Definition
42// ------------------------------------------------------------------------------
43
44const messages = {
45 wrongIndent: 'Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}.',
46};
47
48module.exports = {
49 meta: {
50 docs: {
51 description: 'Enforce props indentation in JSX',
52 category: 'Stylistic Issues',
53 recommended: false,
54 url: docsUrl('jsx-indent-props'),
55 },
56 fixable: 'code',
57
58 messages,
59
60 schema: [{
61 anyOf: [{
62 enum: ['tab', 'first'],
63 }, {
64 type: 'integer',
65 }, {
66 type: 'object',
67 properties: {
68 indentMode: {
69 anyOf: [{
70 enum: ['tab', 'first'],
71 }, {
72 type: 'integer',
73 }],
74 },
75 ignoreTernaryOperator: {
76 type: 'boolean',
77 },
78 },
79 }],
80 }],
81 },
82
83 create(context) {
84 const extraColumnStart = 0;
85 let indentType = 'space';
86 /** @type {number|'first'} */
87 let indentSize = 4;
88 const line = {
89 isUsingOperator: false,
90 currentOperator: false,
91 };
92 let ignoreTernaryOperator = false;
93
94 if (context.options.length) {
95 const isConfigObject = typeof context.options[0] === 'object';
96 const indentMode = isConfigObject
97 ? context.options[0].indentMode
98 : context.options[0];
99
100 if (indentMode === 'first') {
101 indentSize = 'first';
102 indentType = 'space';
103 } else if (indentMode === 'tab') {
104 indentSize = 1;
105 indentType = 'tab';
106 } else if (typeof indentMode === 'number') {
107 indentSize = indentMode;
108 indentType = 'space';
109 }
110
111 if (isConfigObject && context.options[0].ignoreTernaryOperator) {
112 ignoreTernaryOperator = true;
113 }
114 }
115
116 /**
117 * Reports a given indent violation and properly pluralizes the message
118 * @param {ASTNode} node Node violating the indent rule
119 * @param {Number} needed Expected indentation character count
120 * @param {Number} gotten Indentation character count in the actual node/code
121 */
122 function report(node, needed, gotten) {
123 const msgContext = {
124 needed,
125 type: indentType,
126 characters: needed === 1 ? 'character' : 'characters',
127 gotten,
128 };
129
130 reportC(context, messages.wrongIndent, 'wrongIndent', {
131 node,
132 data: msgContext,
133 fix(fixer) {
134 return fixer.replaceTextRange([node.range[0] - node.loc.start.column, node.range[0]],
135 repeat(indentType === 'space' ? ' ' : '\t', needed)
136 );
137 },
138 });
139 }
140
141 /**
142 * Get node indent
143 * @param {ASTNode} node Node to examine
144 * @return {Number} Indent
145 */
146 function getNodeIndent(node) {
147 let src = getText(context, node, node.loc.start.column + extraColumnStart);
148 const lines = src.split('\n');
149 src = lines[0];
150
151 let regExp;
152 if (indentType === 'space') {
153 regExp = /^[ ]+/;
154 } else {
155 regExp = /^[\t]+/;
156 }
157
158 const indent = regExp.exec(src);
159 const useOperator = /^([ ]|[\t])*[:]/.test(src) || /^([ ]|[\t])*[?]/.test(src);
160 const useBracket = /[<]/.test(src);
161
162 line.currentOperator = false;
163 if (useOperator) {
164 line.isUsingOperator = true;
165 line.currentOperator = true;
166 } else if (useBracket) {
167 line.isUsingOperator = false;
168 }
169
170 return indent ? indent[0].length : 0;
171 }
172
173 /**
174 * Check indent for nodes list
175 * @param {ASTNode[]} nodes list of node objects
176 * @param {Number} indent needed indent
177 */
178 function checkNodesIndent(nodes, indent) {
179 let nestedIndent = indent;
180 nodes.forEach((node) => {
181 const nodeIndent = getNodeIndent(node);
182 if (
183 line.isUsingOperator
184 && !line.currentOperator
185 && indentSize !== 'first'
186 && !ignoreTernaryOperator
187 ) {
188 nestedIndent += indentSize;
189 line.isUsingOperator = false;
190 }
191 if (
192 node.type !== 'ArrayExpression' && node.type !== 'ObjectExpression'
193 && nodeIndent !== nestedIndent && astUtil.isNodeFirstInLine(context, node)
194 ) {
195 report(node, nestedIndent, nodeIndent);
196 }
197 });
198 }
199
200 return {
201 JSXOpeningElement(node) {
202 if (!node.attributes.length) {
203 return;
204 }
205 let propIndent;
206 if (indentSize === 'first') {
207 const firstPropNode = node.attributes[0];
208 propIndent = firstPropNode.loc.start.column;
209 } else {
210 const elementIndent = getNodeIndent(node);
211 propIndent = elementIndent + indentSize;
212 }
213 checkNodesIndent(node.attributes, propIndent);
214 },
215 };
216 },
217};
Note: See TracBrowser for help on using the repository browser.