92 lines
2.4 KiB
Plaintext
92 lines
2.4 KiB
Plaintext
import propName from './propName';
|
|
|
|
const DEFAULT_OPTIONS = {
|
|
ignoreCase: true,
|
|
};
|
|
|
|
/**
|
|
* Returns the JSXAttribute itself or undefined, indicating the prop
|
|
* is not present on the JSXOpeningElement.
|
|
*
|
|
*/
|
|
export default function getProp(props = [], prop = '', options = DEFAULT_OPTIONS) {
|
|
function getName(name) { return options.ignoreCase ? name.toUpperCase() : name; }
|
|
const propToFind = getName(prop);
|
|
function isPropToFind(property) {
|
|
return property.type === 'Property'
|
|
&& property.key.type === 'Identifier'
|
|
&& propToFind === getName(property.key.name);
|
|
}
|
|
|
|
const foundAttribute = props.find((attribute) => {
|
|
// If the props contain a spread prop, try to find the property in the object expression.
|
|
if (attribute.type === 'JSXSpreadAttribute') {
|
|
return attribute.argument.type === 'ObjectExpression'
|
|
&& propToFind !== getName('key') // https://github.com/reactjs/rfcs/pull/107
|
|
&& attribute.argument.properties.some(isPropToFind);
|
|
}
|
|
|
|
return propToFind === getName(propName(attribute));
|
|
});
|
|
|
|
if (foundAttribute && foundAttribute.type === 'JSXSpreadAttribute') {
|
|
return propertyToJSXAttribute(foundAttribute.argument.properties.find(isPropToFind));
|
|
}
|
|
|
|
return foundAttribute;
|
|
}
|
|
|
|
function propertyToJSXAttribute(node) {
|
|
const { key, value } = node;
|
|
return {
|
|
type: 'JSXAttribute',
|
|
name: { type: 'JSXIdentifier', name: key.name, ...getBaseProps(key) },
|
|
value: value.type === 'Literal'
|
|
? adjustRangeOfNode(value)
|
|
: { type: 'JSXExpressionContainer', expression: adjustExpressionRange(value), ...getBaseProps(value) },
|
|
...getBaseProps(node),
|
|
};
|
|
}
|
|
|
|
function adjustRangeOfNode(node) {
|
|
const [start, end] = node.range || [node.start, node.end];
|
|
|
|
return {
|
|
...node,
|
|
end: undefined,
|
|
range: [start, end],
|
|
start: undefined,
|
|
};
|
|
}
|
|
|
|
function adjustExpressionRange({ expressions, quasis, ...expression }) {
|
|
return {
|
|
...adjustRangeOfNode(expression),
|
|
...(expressions ? { expressions: expressions.map(adjustRangeOfNode) } : {}),
|
|
...(quasis ? { quasis: quasis.map(adjustRangeOfNode) } : {}),
|
|
};
|
|
}
|
|
|
|
function getBaseProps({ loc, ...node }) {
|
|
const { range } = adjustRangeOfNode(node);
|
|
|
|
return {
|
|
loc: getBaseLocation(loc),
|
|
range,
|
|
};
|
|
}
|
|
|
|
function getBaseLocation({
|
|
start,
|
|
end,
|
|
source,
|
|
filename,
|
|
}) {
|
|
return {
|
|
start,
|
|
end,
|
|
...(source !== undefined ? { source } : {}),
|
|
...(filename !== undefined ? { filename } : {}),
|
|
};
|
|
}
|