jsx-space-before-closing.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * @fileoverview Validate spacing before closing bracket in JSX.
  3. * @author ryym
  4. * @deprecated
  5. */
  6. 'use strict';
  7. const getTokenBeforeClosingBracket = require('../util/getTokenBeforeClosingBracket');
  8. const docsUrl = require('../util/docsUrl');
  9. const log = require('../util/log');
  10. const report = require('../util/report');
  11. let isWarnedForDeprecation = false;
  12. // ------------------------------------------------------------------------------
  13. // Rule Definition
  14. // ------------------------------------------------------------------------------
  15. const messages = {
  16. noSpaceBeforeClose: 'A space is forbidden before closing bracket',
  17. needSpaceBeforeClose: 'A space is required before closing bracket',
  18. };
  19. module.exports = {
  20. meta: {
  21. deprecated: true,
  22. replacedBy: ['jsx-tag-spacing'],
  23. docs: {
  24. description: 'Enforce spacing before closing bracket in JSX',
  25. category: 'Stylistic Issues',
  26. recommended: false,
  27. url: docsUrl('jsx-space-before-closing'),
  28. },
  29. fixable: 'code',
  30. messages,
  31. schema: [{
  32. enum: ['always', 'never'],
  33. }],
  34. },
  35. create(context) {
  36. const configuration = context.options[0] || 'always';
  37. // --------------------------------------------------------------------------
  38. // Public
  39. // --------------------------------------------------------------------------
  40. return {
  41. JSXOpeningElement(node) {
  42. if (!node.selfClosing) {
  43. return;
  44. }
  45. const sourceCode = context.getSourceCode();
  46. const leftToken = getTokenBeforeClosingBracket(node);
  47. const closingSlash = sourceCode.getTokenAfter(leftToken);
  48. if (leftToken.loc.end.line !== closingSlash.loc.start.line) {
  49. return;
  50. }
  51. if (configuration === 'always' && !sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
  52. report(context, messages.needSpaceBeforeClose, 'needSpaceBeforeClose', {
  53. loc: closingSlash.loc.start,
  54. fix(fixer) {
  55. return fixer.insertTextBefore(closingSlash, ' ');
  56. },
  57. });
  58. } else if (configuration === 'never' && sourceCode.isSpaceBetweenTokens(leftToken, closingSlash)) {
  59. report(context, messages.noSpaceBeforeClose, 'noSpaceBeforeClose', {
  60. loc: closingSlash.loc.start,
  61. fix(fixer) {
  62. const previousToken = sourceCode.getTokenBefore(closingSlash);
  63. return fixer.removeRange([previousToken.range[1], closingSlash.range[0]]);
  64. },
  65. });
  66. }
  67. },
  68. Program() {
  69. if (isWarnedForDeprecation) {
  70. return;
  71. }
  72. log('The react/jsx-space-before-closing rule is deprecated. '
  73. + 'Please use the react/jsx-tag-spacing rule with the '
  74. + '"beforeSelfClosing" option instead.');
  75. isWarnedForDeprecation = true;
  76. },
  77. };
  78. },
  79. };