source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-max-props-per-line.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: 4.1 KB
RevLine 
[d565449]1/**
2 * @fileoverview Limit maximum of props on a single line in JSX
3 * @author Yannick Croissant
4 */
5
6'use strict';
7
8const docsUrl = require('../util/docsUrl');
9const getText = require('../util/eslint').getText;
10const report = require('../util/report');
11
12function getPropName(context, propNode) {
13 if (propNode.type === 'JSXSpreadAttribute') {
14 return getText(context, propNode.argument);
15 }
16 return propNode.name.name;
17}
18
19// ------------------------------------------------------------------------------
20// Rule Definition
21// ------------------------------------------------------------------------------
22
23const messages = {
24 newLine: 'Prop `{{prop}}` must be placed on a new line',
25};
26
27/** @type {import('eslint').Rule.RuleModule} */
28module.exports = {
29 meta: {
30 docs: {
31 description: 'Enforce maximum of props on a single line in JSX',
32 category: 'Stylistic Issues',
33 recommended: false,
34 url: docsUrl('jsx-max-props-per-line'),
35 },
36 fixable: 'code',
37
38 messages,
39
40 schema: [{
41 anyOf: [{
42 type: 'object',
43 properties: {
44 maximum: {
45 type: 'object',
46 properties: {
47 single: {
48 type: 'integer',
49 minimum: 1,
50 },
51 multi: {
52 type: 'integer',
53 minimum: 1,
54 },
55 },
56 },
57 },
58 additionalProperties: false,
59 }, {
60 type: 'object',
61 properties: {
62 maximum: {
63 type: 'number',
64 minimum: 1,
65 },
66 when: {
67 type: 'string',
68 enum: ['always', 'multiline'],
69 },
70 },
71 additionalProperties: false,
72 }],
73 }],
74 },
75
76 create(context) {
77 const configuration = context.options[0] || {};
78 const maximum = configuration.maximum || 1;
79
80 const maxConfig = typeof maximum === 'number'
81 ? {
82 single: configuration.when === 'multiline' ? Infinity : maximum,
83 multi: maximum,
84 }
85 : {
86 single: maximum.single || Infinity,
87 multi: maximum.multi || Infinity,
88 };
89
90 function generateFixFunction(line, max) {
91 const output = [];
92 const front = line[0].range[0];
93 const back = line[line.length - 1].range[1];
94
95 for (let i = 0; i < line.length; i += max) {
96 const nodes = line.slice(i, i + max);
97 output.push(nodes.reduce((prev, curr) => {
98 if (prev === '') {
99 return getText(context, curr);
100 }
101 return `${prev} ${getText(context, curr)}`;
102 }, ''));
103 }
104
105 const code = output.join('\n');
106
107 return function fix(fixer) {
108 return fixer.replaceTextRange([front, back], code);
109 };
110 }
111
112 return {
113 JSXOpeningElement(node) {
114 if (!node.attributes.length) {
115 return;
116 }
117
118 const isSingleLineTag = node.loc.start.line === node.loc.end.line;
119
120 if ((isSingleLineTag ? maxConfig.single : maxConfig.multi) === Infinity) {
121 return;
122 }
123
124 const firstProp = node.attributes[0];
125 const linePartitionedProps = [[firstProp]];
126
127 node.attributes.reduce((last, decl) => {
128 if (last.loc.end.line === decl.loc.start.line) {
129 linePartitionedProps[linePartitionedProps.length - 1].push(decl);
130 } else {
131 linePartitionedProps.push([decl]);
132 }
133 return decl;
134 });
135
136 linePartitionedProps.forEach((propsInLine) => {
137 const maxPropsCountPerLine = isSingleLineTag && propsInLine[0].loc.start.line === node.loc.start.line
138 ? maxConfig.single
139 : maxConfig.multi;
140
141 if (propsInLine.length > maxPropsCountPerLine) {
142 const name = getPropName(context, propsInLine[maxPropsCountPerLine]);
143 report(context, messages.newLine, 'newLine', {
144 node: propsInLine[maxPropsCountPerLine],
145 data: {
146 prop: name,
147 },
148 fix: generateFixFunction(propsInLine, maxPropsCountPerLine),
149 });
150 }
151 });
152 },
153 };
154 },
155};
Note: See TracBrowser for help on using the repository browser.