source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/self-closing-comp.js@ 0c6b92a

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

Pred finalna verzija

  • Property mode set to 100644
File size: 2.9 KB
RevLine 
[d565449]1/**
2 * @fileoverview Prevent extra closing tags for components without children
3 * @author Yannick Croissant
4 */
5
6'use strict';
7
8const docsUrl = require('../util/docsUrl');
9const jsxUtil = require('../util/jsx');
10const report = require('../util/report');
11
[0c6b92a]12const optionDefaults = { component: true, html: true };
13
14function isComponent(node) {
15 return (
16 node.name
17 && (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression')
18 && !jsxUtil.isDOMComponent(node)
19 );
20}
21
22function childrenIsEmpty(node) {
23 return node.parent.children.length === 0;
24}
25
26function childrenIsMultilineSpaces(node) {
27 const childrens = node.parent.children;
28
29 return (
30 childrens.length === 1
31 && (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText')
32 && childrens[0].value.indexOf('\n') !== -1
33 && childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
34 );
35}
36
[d565449]37// ------------------------------------------------------------------------------
38// Rule Definition
39// ------------------------------------------------------------------------------
40
41const messages = {
42 notSelfClosing: 'Empty components are self-closing',
43};
44
45/** @type {import('eslint').Rule.RuleModule} */
46module.exports = {
47 meta: {
48 docs: {
49 description: 'Disallow extra closing tags for components without children',
50 category: 'Stylistic Issues',
51 recommended: false,
52 url: docsUrl('self-closing-comp'),
53 },
54 fixable: 'code',
55
56 messages,
57
58 schema: [{
59 type: 'object',
60 properties: {
61 component: {
62 default: optionDefaults.component,
63 type: 'boolean',
64 },
65 html: {
66 default: optionDefaults.html,
67 type: 'boolean',
68 },
69 },
70 additionalProperties: false,
71 }],
72 },
73
74 create(context) {
75 function isShouldBeSelfClosed(node) {
76 const configuration = Object.assign({}, optionDefaults, context.options[0]);
77 return (
78 (configuration.component && isComponent(node))
79 || (configuration.html && jsxUtil.isDOMComponent(node))
80 ) && !node.selfClosing && (childrenIsEmpty(node) || childrenIsMultilineSpaces(node));
81 }
82
83 return {
84 JSXOpeningElement(node) {
85 if (!isShouldBeSelfClosed(node)) {
86 return;
87 }
88 report(context, messages.notSelfClosing, 'notSelfClosing', {
89 node,
90 fix(fixer) {
91 // Represents the last character of the JSXOpeningElement, the '>' character
92 const openingElementEnding = node.range[1] - 1;
93 // Represents the last character of the JSXClosingElement, the '>' character
94 const closingElementEnding = node.parent.closingElement.range[1];
95
96 // Replace />.*<\/.*>/ with '/>'
97 const range = [openingElementEnding, closingElementEnding];
98 return fixer.replaceTextRange(range, ' />');
99 },
100 });
101 },
102 };
103 },
104};
Note: See TracBrowser for help on using the repository browser.