source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/no-danger-with-children.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: 5.1 KB
Line 
1/**
2 * @fileoverview Report when a DOM element is using both children and dangerouslySetInnerHTML
3 * @author David Petersen
4 */
5
6'use strict';
7
8const variableUtil = require('../util/variable');
9const jsxUtil = require('../util/jsx');
10const docsUrl = require('../util/docsUrl');
11const report = require('../util/report');
12
13// ------------------------------------------------------------------------------
14// Rule Definition
15// ------------------------------------------------------------------------------
16const messages = {
17 dangerWithChildren: 'Only set one of `children` or `props.dangerouslySetInnerHTML`',
18};
19
20/** @type {import('eslint').Rule.RuleModule} */
21module.exports = {
22 meta: {
23 docs: {
24 description: 'Disallow when a DOM element is using both children and dangerouslySetInnerHTML',
25 category: 'Possible Errors',
26 recommended: true,
27 url: docsUrl('no-danger-with-children'),
28 },
29
30 messages,
31
32 schema: [], // no options
33 },
34 create(context) {
35 function findSpreadVariable(node, name) {
36 return variableUtil.getVariableFromContext(context, node, name);
37 }
38 /**
39 * Takes a ObjectExpression and returns the value of the prop if it has it
40 * @param {object} node - ObjectExpression node
41 * @param {string} propName - name of the prop to look for
42 * @param {string[]} seenProps
43 * @returns {object | boolean}
44 */
45 function findObjectProp(node, propName, seenProps) {
46 if (!node.properties) {
47 return false;
48 }
49 return node.properties.find((prop) => {
50 if (prop.type === 'Property') {
51 return prop.key.name === propName;
52 }
53 if (prop.type === 'ExperimentalSpreadProperty' || prop.type === 'SpreadElement') {
54 const variable = findSpreadVariable(node, prop.argument.name);
55 if (variable && variable.defs.length && variable.defs[0].node.init) {
56 if (seenProps.indexOf(prop.argument.name) > -1) {
57 return false;
58 }
59 const newSeenProps = seenProps.concat(prop.argument.name || []);
60 return findObjectProp(variable.defs[0].node.init, propName, newSeenProps);
61 }
62 }
63 return false;
64 });
65 }
66
67 /**
68 * Takes a JSXElement and returns the value of the prop if it has it
69 * @param {object} node - JSXElement node
70 * @param {string} propName - name of the prop to look for
71 * @returns {object | boolean}
72 */
73 function findJsxProp(node, propName) {
74 const attributes = node.openingElement.attributes;
75 return attributes.find((attribute) => {
76 if (attribute.type === 'JSXSpreadAttribute') {
77 const variable = findSpreadVariable(node, attribute.argument.name);
78 if (variable && variable.defs.length && variable.defs[0].node.init) {
79 return findObjectProp(variable.defs[0].node.init, propName, []);
80 }
81 }
82 return attribute.name && attribute.name.name === propName;
83 });
84 }
85
86 /**
87 * Checks to see if a node is a line break
88 * @param {ASTNode} node The AST node being checked
89 * @returns {boolean} True if node is a line break, false if not
90 */
91 function isLineBreak(node) {
92 const isLiteral = node.type === 'Literal' || node.type === 'JSXText';
93 const isMultiline = node.loc.start.line !== node.loc.end.line;
94 const isWhiteSpaces = jsxUtil.isWhiteSpaces(node.value);
95
96 return isLiteral && isMultiline && isWhiteSpaces;
97 }
98
99 return {
100 JSXElement(node) {
101 let hasChildren = false;
102
103 if (node.children.length && !isLineBreak(node.children[0])) {
104 hasChildren = true;
105 } else if (findJsxProp(node, 'children')) {
106 hasChildren = true;
107 }
108
109 if (
110 node.openingElement.attributes
111 && hasChildren
112 && findJsxProp(node, 'dangerouslySetInnerHTML')
113 ) {
114 report(context, messages.dangerWithChildren, 'dangerWithChildren', {
115 node,
116 });
117 }
118 },
119 CallExpression(node) {
120 if (
121 node.callee
122 && node.callee.type === 'MemberExpression'
123 && 'name' in node.callee.property
124 && node.callee.property.name === 'createElement'
125 && node.arguments.length > 1
126 ) {
127 let hasChildren = false;
128
129 let props = node.arguments[1];
130
131 if (props.type === 'Identifier') {
132 const variable = variableUtil.getVariableFromContext(context, node, props.name);
133 if (variable && variable.defs.length && variable.defs[0].node.init) {
134 props = variable.defs[0].node.init;
135 }
136 }
137
138 const dangerously = findObjectProp(props, 'dangerouslySetInnerHTML', []);
139
140 if (node.arguments.length === 2) {
141 if (findObjectProp(props, 'children', [])) {
142 hasChildren = true;
143 }
144 } else {
145 hasChildren = true;
146 }
147
148 if (dangerously && hasChildren) {
149 report(context, messages.dangerWithChildren, 'dangerWithChildren', {
150 node,
151 });
152 }
153 }
154 },
155 };
156 },
157};
Note: See TracBrowser for help on using the repository browser.