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

main
Last change on this file since 0c6b92a was 0c6b92a, checked in by stefan toskovski <stefantoska84@…>, 5 weeks ago

Pred finalna verzija

  • Property mode set to 100644
File size: 6.4 KB
RevLine 
[d565449]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
[0c6b92a]48/** @type {import('eslint').Rule.RuleModule} */
[d565449]49module.exports = {
50 meta: {
51 docs: {
52 description: 'Enforce props indentation in JSX',
53 category: 'Stylistic Issues',
54 recommended: false,
55 url: docsUrl('jsx-indent-props'),
56 },
57 fixable: 'code',
58
59 messages,
60
61 schema: [{
62 anyOf: [{
63 enum: ['tab', 'first'],
64 }, {
65 type: 'integer',
66 }, {
67 type: 'object',
68 properties: {
69 indentMode: {
70 anyOf: [{
71 enum: ['tab', 'first'],
72 }, {
73 type: 'integer',
74 }],
75 },
76 ignoreTernaryOperator: {
77 type: 'boolean',
78 },
79 },
80 }],
81 }],
82 },
83
84 create(context) {
85 const extraColumnStart = 0;
86 let indentType = 'space';
87 /** @type {number|'first'} */
88 let indentSize = 4;
89 const line = {
90 isUsingOperator: false,
91 currentOperator: false,
92 };
93 let ignoreTernaryOperator = false;
94
95 if (context.options.length) {
96 const isConfigObject = typeof context.options[0] === 'object';
97 const indentMode = isConfigObject
98 ? context.options[0].indentMode
99 : context.options[0];
100
101 if (indentMode === 'first') {
102 indentSize = 'first';
103 indentType = 'space';
104 } else if (indentMode === 'tab') {
105 indentSize = 1;
106 indentType = 'tab';
107 } else if (typeof indentMode === 'number') {
108 indentSize = indentMode;
109 indentType = 'space';
110 }
111
112 if (isConfigObject && context.options[0].ignoreTernaryOperator) {
113 ignoreTernaryOperator = true;
114 }
115 }
116
117 /**
118 * Reports a given indent violation and properly pluralizes the message
119 * @param {ASTNode} node Node violating the indent rule
[0c6b92a]120 * @param {number} needed Expected indentation character count
121 * @param {number} gotten Indentation character count in the actual node/code
[d565449]122 */
123 function report(node, needed, gotten) {
124 const msgContext = {
125 needed,
126 type: indentType,
127 characters: needed === 1 ? 'character' : 'characters',
128 gotten,
129 };
130
131 reportC(context, messages.wrongIndent, 'wrongIndent', {
132 node,
133 data: msgContext,
134 fix(fixer) {
135 return fixer.replaceTextRange([node.range[0] - node.loc.start.column, node.range[0]],
136 repeat(indentType === 'space' ? ' ' : '\t', needed)
137 );
138 },
139 });
140 }
141
142 /**
143 * Get node indent
144 * @param {ASTNode} node Node to examine
[0c6b92a]145 * @return {number} Indent
[d565449]146 */
147 function getNodeIndent(node) {
148 let src = getText(context, node, node.loc.start.column + extraColumnStart);
149 const lines = src.split('\n');
150 src = lines[0];
151
152 let regExp;
153 if (indentType === 'space') {
154 regExp = /^[ ]+/;
155 } else {
156 regExp = /^[\t]+/;
157 }
158
159 const indent = regExp.exec(src);
160 const useOperator = /^([ ]|[\t])*[:]/.test(src) || /^([ ]|[\t])*[?]/.test(src);
161 const useBracket = /[<]/.test(src);
162
163 line.currentOperator = false;
164 if (useOperator) {
165 line.isUsingOperator = true;
166 line.currentOperator = true;
167 } else if (useBracket) {
168 line.isUsingOperator = false;
169 }
170
171 return indent ? indent[0].length : 0;
172 }
173
174 /**
175 * Check indent for nodes list
176 * @param {ASTNode[]} nodes list of node objects
[0c6b92a]177 * @param {number} indent needed indent
[d565449]178 */
179 function checkNodesIndent(nodes, indent) {
180 let nestedIndent = indent;
181 nodes.forEach((node) => {
182 const nodeIndent = getNodeIndent(node);
183 if (
184 line.isUsingOperator
185 && !line.currentOperator
186 && indentSize !== 'first'
187 && !ignoreTernaryOperator
188 ) {
189 nestedIndent += indentSize;
190 line.isUsingOperator = false;
191 }
192 if (
193 node.type !== 'ArrayExpression' && node.type !== 'ObjectExpression'
194 && nodeIndent !== nestedIndent && astUtil.isNodeFirstInLine(context, node)
195 ) {
196 report(node, nestedIndent, nodeIndent);
197 }
198 });
199 }
200
201 return {
202 JSXOpeningElement(node) {
203 if (!node.attributes.length) {
204 return;
205 }
206 let propIndent;
207 if (indentSize === 'first') {
208 const firstPropNode = node.attributes[0];
209 propIndent = firstPropNode.loc.start.column;
210 } else {
211 const elementIndent = getNodeIndent(node);
212 propIndent = elementIndent + indentSize;
213 }
214 checkNodesIndent(node.attributes, propIndent);
215 },
216 };
217 },
218};
Note: See TracBrowser for help on using the repository browser.