source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-pascal-case.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/**
2 * @fileoverview Enforce PascalCase for user-defined JSX components
3 * @author Jake Marsh
4 */
5
6'use strict';
7
8const elementType = require('jsx-ast-utils/elementType');
9const minimatch = require('minimatch');
10const docsUrl = require('../util/docsUrl');
11const jsxUtil = require('../util/jsx');
12const report = require('../util/report');
13
14function testDigit(char) {
15 const charCode = char.charCodeAt(0);
16 return charCode >= 48 && charCode <= 57;
17}
18
19function testUpperCase(char) {
20 const upperCase = char.toUpperCase();
21 return char === upperCase && upperCase !== char.toLowerCase();
22}
23
24function testLowerCase(char) {
25 const lowerCase = char.toLowerCase();
26 return char === lowerCase && lowerCase !== char.toUpperCase();
27}
28
29function testPascalCase(name) {
30 if (!testUpperCase(name.charAt(0))) {
31 return false;
32 }
33 const anyNonAlphaNumeric = Array.prototype.some.call(
34 name.slice(1),
35 (char) => char.toLowerCase() === char.toUpperCase() && !testDigit(char)
36 );
37 if (anyNonAlphaNumeric) {
38 return false;
39 }
40 return Array.prototype.some.call(
41 name.slice(1),
42 (char) => testLowerCase(char) || testDigit(char)
43 );
44}
45
46function testAllCaps(name) {
47 const firstChar = name.charAt(0);
48 if (!(testUpperCase(firstChar) || testDigit(firstChar))) {
49 return false;
50 }
51 for (let i = 1; i < name.length - 1; i += 1) {
52 const char = name.charAt(i);
53 if (!(testUpperCase(char) || testDigit(char) || char === '_')) {
54 return false;
55 }
56 }
57 const lastChar = name.charAt(name.length - 1);
58 if (!(testUpperCase(lastChar) || testDigit(lastChar))) {
59 return false;
60 }
61 return true;
62}
63
64function ignoreCheck(ignore, name) {
65 return ignore.some(
66 (entry) => name === entry || minimatch(name, entry, { noglobstar: true })
67 );
68}
69
70// ------------------------------------------------------------------------------
71// Rule Definition
72// ------------------------------------------------------------------------------
73
74const messages = {
75 usePascalCase: 'Imported JSX component {{name}} must be in PascalCase',
76 usePascalOrSnakeCase: 'Imported JSX component {{name}} must be in PascalCase or SCREAMING_SNAKE_CASE',
77};
78
79/** @type {import('eslint').Rule.RuleModule} */
80module.exports = {
81 meta: {
82 docs: {
83 description: 'Enforce PascalCase for user-defined JSX components',
84 category: 'Stylistic Issues',
85 recommended: false,
86 url: docsUrl('jsx-pascal-case'),
87 },
88
89 messages,
90
91 schema: [{
92 type: 'object',
93 properties: {
94 allowAllCaps: {
95 type: 'boolean',
96 },
97 allowLeadingUnderscore: {
98 type: 'boolean',
99 },
100 allowNamespace: {
101 type: 'boolean',
102 },
103 ignore: {
104 items: [
105 {
106 type: 'string',
107 },
108 ],
109 minItems: 0,
110 type: 'array',
111 uniqueItems: true,
112 },
113 },
114 additionalProperties: false,
115 }],
116 },
117
118 create(context) {
119 const configuration = context.options[0] || {};
120 const allowAllCaps = configuration.allowAllCaps || false;
121 const allowLeadingUnderscore = configuration.allowLeadingUnderscore || false;
122 const allowNamespace = configuration.allowNamespace || false;
123 const ignore = configuration.ignore || [];
124
125 return {
126 JSXOpeningElement(node) {
127 const isCompatTag = jsxUtil.isDOMComponent(node);
128 if (isCompatTag) return undefined;
129
130 const name = elementType(node);
131 let checkNames = [name];
132 let index = 0;
133
134 if (name.lastIndexOf(':') > -1) {
135 checkNames = name.split(':');
136 } else if (name.lastIndexOf('.') > -1) {
137 checkNames = name.split('.');
138 }
139
140 do {
141 const splitName = checkNames[index];
142 if (splitName.length === 1) return undefined;
143 const isIgnored = ignoreCheck(ignore, splitName);
144
145 const checkName = allowLeadingUnderscore && splitName.startsWith('_') ? splitName.slice(1) : splitName;
146 const isPascalCase = testPascalCase(checkName);
147 const isAllowedAllCaps = allowAllCaps && testAllCaps(checkName);
148
149 if (!isPascalCase && !isAllowedAllCaps && !isIgnored) {
150 const messageId = allowAllCaps ? 'usePascalOrSnakeCase' : 'usePascalCase';
151 report(context, messages[messageId], messageId, {
152 node,
153 data: {
154 name: splitName,
155 },
156 });
157 break;
158 }
159 index += 1;
160 } while (index < checkNames.length && !allowNamespace);
161 },
162 };
163 },
164};
Note: See TracBrowser for help on using the repository browser.