UNPKG

victory-core

Version:
97 lines (88 loc) 3.19 kB
import * as React from "react"; import { evaluateProp } from "./helpers"; /* USER_PROPS_SAFELIST is to contain any string deemed safe for user props. The startsWidth array will contain the start of any accepted user-prop that starts with these characters. The exactMatch will contain a list of exact prop names that are accepted. */ const USER_PROPS_SAFELIST = { startsWith: ["data-", "aria-"], exactMatch: [] }; // Normally we'd use Template Literal Types, but we're avoiding it to maximize TS compatibility with TS < 4.1 // `data-${string}` | `aria-${string}`; /** * doesPropStartWith: Function that takes a prop's key and runs it against all * options in the USER_PROPS_SAFELIST and checks to see if it starts with any * of those options. * @param {string} key: prop key to be tested against whitelist * @returns {Boolean}: returns true if the key starts with an option or false if * otherwise */ const doesPropStartWith = key => { let startsWith = false; USER_PROPS_SAFELIST.startsWith.forEach(starterString => { const regex = new RegExp(`\\b(${starterString})(\\w|-)+`, "g"); if (regex.test(key)) startsWith = true; }); return startsWith; }; /** * isExactMatch: checks to see if the given key matches any of the 'exactMatch' * items in the whitelist * @param {String} key: prop key to be tested against the whitelist-exact match * array. * @returns {Boolean}: return true if whitelist contains that key, otherwise * returns false. */ const isExactMatch = key => USER_PROPS_SAFELIST.exactMatch.includes(key); /** * testIfSafeProp: tests prop's key against both startsWith and exactMatch values * @param {String} key: prop key to be tested against the whitelist * @returns {Boolean}: returns true if found in whitelist, otherwise returns false */ const testIfSafeProp = key => { if (doesPropStartWith(key) || isExactMatch(key)) return true; return false; }; /** * Asserts that value is not null or undefined, throwing an error if it is. * @param value The value to assert * @param message The error message to throw */ export function assert(value, message) { if (value === undefined || value === null) { throw new Error(message); } } /** * getSafeUserProps - function that takes in a props object and removes any * key-value entries that do not match filter strings in the USER_PROPS_SAFELIST * object. * * @param {Object} props: props to be filtered against USER_PROPS_SAFELIST * @returns {Object}: object containing remaining acceptable props */ export const getSafeUserProps = props => { const propsToFilter = { ...props }; return Object.fromEntries(Object.entries(propsToFilter).filter(_ref => { let [key] = _ref; return testIfSafeProp(key); }).map(_ref2 => { let [key, value] = _ref2; return [key, evaluateProp(value, props)]; })); }; /** * Wraps a component and adds safe user props * * @param {ReactElement} component: parent component * @param {Object} props: props to be filtered * @returns {ReactElement} modified component */ export const withSafeUserProps = (component, props) => { return /*#__PURE__*/React.cloneElement(component, getSafeUserProps(props)); };