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

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

Update repo after prototype presentation

  • 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
12// ------------------------------------------------------------------------------
13// Rule Definition
14// ------------------------------------------------------------------------------
15
16const optionDefaults = { component: true, html: true };
17
18const messages = {
19 notSelfClosing: 'Empty components are self-closing',
20};
21
22/** @type {import('eslint').Rule.RuleModule} */
23module.exports = {
24 meta: {
25 docs: {
26 description: 'Disallow extra closing tags for components without children',
27 category: 'Stylistic Issues',
28 recommended: false,
29 url: docsUrl('self-closing-comp'),
30 },
31 fixable: 'code',
32
33 messages,
34
35 schema: [{
36 type: 'object',
37 properties: {
38 component: {
39 default: optionDefaults.component,
40 type: 'boolean',
41 },
42 html: {
43 default: optionDefaults.html,
44 type: 'boolean',
45 },
46 },
47 additionalProperties: false,
48 }],
49 },
50
51 create(context) {
52 function isComponent(node) {
53 return (
54 node.name
55 && (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression')
56 && !jsxUtil.isDOMComponent(node)
57 );
58 }
59
60 function childrenIsEmpty(node) {
61 return node.parent.children.length === 0;
62 }
63
64 function childrenIsMultilineSpaces(node) {
65 const childrens = node.parent.children;
66
67 return (
68 childrens.length === 1
69 && (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText')
70 && childrens[0].value.indexOf('\n') !== -1
71 && childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
72 );
73 }
74
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.