Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

106 righe
2.9 KiB

  1. /**
  2. * @fileoverview Limit maximum of props on a single line in JSX
  3. * @author Yannick Croissant
  4. */
  5. 'use strict';
  6. const docsUrl = require('../util/docsUrl');
  7. // ------------------------------------------------------------------------------
  8. // Rule Definition
  9. // ------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. docs: {
  13. description: 'Limit maximum of props on a single line in JSX',
  14. category: 'Stylistic Issues',
  15. recommended: false,
  16. url: docsUrl('jsx-max-props-per-line')
  17. },
  18. fixable: 'code',
  19. schema: [{
  20. type: 'object',
  21. properties: {
  22. maximum: {
  23. type: 'integer',
  24. minimum: 1
  25. },
  26. when: {
  27. type: 'string',
  28. enum: ['always', 'multiline']
  29. }
  30. }
  31. }]
  32. },
  33. create: function (context) {
  34. const sourceCode = context.getSourceCode();
  35. const configuration = context.options[0] || {};
  36. const maximum = configuration.maximum || 1;
  37. const when = configuration.when || 'always';
  38. function getPropName(propNode) {
  39. if (propNode.type === 'JSXSpreadAttribute') {
  40. return sourceCode.getText(propNode.argument);
  41. }
  42. return propNode.name.name;
  43. }
  44. function generateFixFunction(line, max) {
  45. const output = [];
  46. const front = line[0].range[0];
  47. const back = line[line.length - 1].range[1];
  48. for (let i = 0; i < line.length; i += max) {
  49. const nodes = line.slice(i, i + max);
  50. output.push(nodes.reduce((prev, curr) => {
  51. if (prev === '') {
  52. return sourceCode.getText(curr);
  53. }
  54. return `${prev} ${sourceCode.getText(curr)}`;
  55. }, ''));
  56. }
  57. const code = output.join('\n');
  58. return function(fixer) {
  59. return fixer.replaceTextRange([front, back], code);
  60. };
  61. }
  62. return {
  63. JSXOpeningElement: function (node) {
  64. if (!node.attributes.length) {
  65. return;
  66. }
  67. if (when === 'multiline' && node.loc.start.line === node.loc.end.line) {
  68. return;
  69. }
  70. const firstProp = node.attributes[0];
  71. const linePartitionedProps = [[firstProp]];
  72. node.attributes.reduce((last, decl) => {
  73. if (last.loc.end.line === decl.loc.start.line) {
  74. linePartitionedProps[linePartitionedProps.length - 1].push(decl);
  75. } else {
  76. linePartitionedProps.push([decl]);
  77. }
  78. return decl;
  79. });
  80. linePartitionedProps.forEach(propsInLine => {
  81. if (propsInLine.length > maximum) {
  82. const name = getPropName(propsInLine[maximum]);
  83. context.report({
  84. node: propsInLine[maximum],
  85. message: `Prop \`${name}\` must be placed on a new line`,
  86. fix: generateFixFunction(propsInLine, maximum)
  87. });
  88. }
  89. });
  90. }
  91. };
  92. }
  93. };