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