jsx-first-prop-new-line.js 2.5 KB

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