no-multi-comp.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /**
  2. * @fileoverview Prevent multiple component definition per file
  3. * @author Yannick Croissant
  4. */
  5. 'use strict';
  6. const values = require('object.values');
  7. const Components = require('../util/Components');
  8. const docsUrl = require('../util/docsUrl');
  9. const report = require('../util/report');
  10. // ------------------------------------------------------------------------------
  11. // Rule Definition
  12. // ------------------------------------------------------------------------------
  13. const messages = {
  14. onlyOneComponent: 'Declare only one React component per file',
  15. };
  16. /** @type {import('eslint').Rule.RuleModule} */
  17. module.exports = {
  18. meta: {
  19. docs: {
  20. description: 'Disallow multiple component definition per file',
  21. category: 'Stylistic Issues',
  22. recommended: false,
  23. url: docsUrl('no-multi-comp'),
  24. },
  25. messages,
  26. schema: [{
  27. type: 'object',
  28. properties: {
  29. ignoreStateless: {
  30. default: false,
  31. type: 'boolean',
  32. },
  33. },
  34. additionalProperties: false,
  35. }],
  36. },
  37. create: Components.detect((context, components, utils) => {
  38. const configuration = context.options[0] || {};
  39. const ignoreStateless = configuration.ignoreStateless || false;
  40. /**
  41. * Checks if the component is ignored
  42. * @param {Object} component The component being checked.
  43. * @returns {boolean} True if the component is ignored, false if not.
  44. */
  45. function isIgnored(component) {
  46. return (
  47. ignoreStateless && (
  48. /Function/.test(component.node.type)
  49. || utils.isPragmaComponentWrapper(component.node)
  50. )
  51. );
  52. }
  53. return {
  54. 'Program:exit'() {
  55. if (components.length() <= 1) {
  56. return;
  57. }
  58. values(components.list())
  59. .filter((component) => !isIgnored(component))
  60. .slice(1)
  61. .forEach((component) => {
  62. report(context, messages.onlyOneComponent, 'onlyOneComponent', {
  63. node: component.node,
  64. });
  65. });
  66. },
  67. };
  68. }),
  69. };