jsx-pascal-case.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /**
  2. * @fileoverview Enforce PascalCase for user-defined JSX components
  3. * @author Jake Marsh
  4. */
  5. 'use strict';
  6. const elementType = require('jsx-ast-utils/elementType');
  7. const docsUrl = require('../util/docsUrl');
  8. // ------------------------------------------------------------------------------
  9. // Constants
  10. // ------------------------------------------------------------------------------
  11. const PASCAL_CASE_REGEX = /^([A-Z0-9]|[A-Z0-9]+[a-z0-9]+(?:[A-Z0-9]+[a-z0-9]*)*)$/;
  12. const COMPAT_TAG_REGEX = /^[a-z]|\-/;
  13. const ALL_CAPS_TAG_REGEX = /^[A-Z0-9]+$/;
  14. // ------------------------------------------------------------------------------
  15. // Rule Definition
  16. // ------------------------------------------------------------------------------
  17. module.exports = {
  18. meta: {
  19. docs: {
  20. description: 'Enforce PascalCase for user-defined JSX components',
  21. category: 'Stylistic Issues',
  22. recommended: false,
  23. url: docsUrl('jsx-pascal-case')
  24. },
  25. schema: [{
  26. type: 'object',
  27. properties: {
  28. allowAllCaps: {
  29. type: 'boolean'
  30. },
  31. ignore: {
  32. type: 'array'
  33. }
  34. },
  35. additionalProperties: false
  36. }]
  37. },
  38. create: function(context) {
  39. const configuration = context.options[0] || {};
  40. const allowAllCaps = configuration.allowAllCaps || false;
  41. const ignore = configuration.ignore || [];
  42. return {
  43. JSXOpeningElement: function(node) {
  44. let name = elementType(node);
  45. // Get namespace if the type is JSXNamespacedName or JSXMemberExpression
  46. if (name.indexOf(':') > -1) {
  47. name = name.substring(0, name.indexOf(':'));
  48. } else if (name.indexOf('.') > -1) {
  49. name = name.substring(0, name.indexOf('.'));
  50. }
  51. const isPascalCase = PASCAL_CASE_REGEX.test(name);
  52. const isCompatTag = COMPAT_TAG_REGEX.test(name);
  53. const isAllowedAllCaps = allowAllCaps && ALL_CAPS_TAG_REGEX.test(name);
  54. const isIgnored = ignore.indexOf(name) !== -1;
  55. if (!isPascalCase && !isCompatTag && !isAllowedAllCaps && !isIgnored) {
  56. context.report({
  57. node: node,
  58. message: `Imported JSX component ${name} must be in PascalCase`
  59. });
  60. }
  61. }
  62. };
  63. }
  64. };