1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  */
    
  7. 
    
  8. import {ATTRIBUTE_NAME_CHAR} from './isAttributeNameSafe';
    
  9. import validAriaProperties from './validAriaProperties';
    
  10. import hasOwnProperty from 'shared/hasOwnProperty';
    
  11. 
    
  12. const warnedProperties = {};
    
  13. const rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
    
  14. const rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
    
  15. 
    
  16. function validateProperty(tagName, name) {
    
  17.   if (__DEV__) {
    
  18.     if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
    
  19.       return true;
    
  20.     }
    
  21. 
    
  22.     if (rARIACamel.test(name)) {
    
  23.       const ariaName = 'aria-' + name.slice(4).toLowerCase();
    
  24.       const correctName = validAriaProperties.hasOwnProperty(ariaName)
    
  25.         ? ariaName
    
  26.         : null;
    
  27. 
    
  28.       // If this is an aria-* attribute, but is not listed in the known DOM
    
  29.       // DOM properties, then it is an invalid aria-* attribute.
    
  30.       if (correctName == null) {
    
  31.         console.error(
    
  32.           'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.',
    
  33.           name,
    
  34.         );
    
  35.         warnedProperties[name] = true;
    
  36.         return true;
    
  37.       }
    
  38.       // aria-* attributes should be lowercase; suggest the lowercase version.
    
  39.       if (name !== correctName) {
    
  40.         console.error(
    
  41.           'Invalid ARIA attribute `%s`. Did you mean `%s`?',
    
  42.           name,
    
  43.           correctName,
    
  44.         );
    
  45.         warnedProperties[name] = true;
    
  46.         return true;
    
  47.       }
    
  48.     }
    
  49. 
    
  50.     if (rARIA.test(name)) {
    
  51.       const lowerCasedName = name.toLowerCase();
    
  52.       const standardName = validAriaProperties.hasOwnProperty(lowerCasedName)
    
  53.         ? lowerCasedName
    
  54.         : null;
    
  55. 
    
  56.       // If this is an aria-* attribute, but is not listed in the known DOM
    
  57.       // DOM properties, then it is an invalid aria-* attribute.
    
  58.       if (standardName == null) {
    
  59.         warnedProperties[name] = true;
    
  60.         return false;
    
  61.       }
    
  62.       // aria-* attributes should be lowercase; suggest the lowercase version.
    
  63.       if (name !== standardName) {
    
  64.         console.error(
    
  65.           'Unknown ARIA attribute `%s`. Did you mean `%s`?',
    
  66.           name,
    
  67.           standardName,
    
  68.         );
    
  69.         warnedProperties[name] = true;
    
  70.         return true;
    
  71.       }
    
  72.     }
    
  73.   }
    
  74. 
    
  75.   return true;
    
  76. }
    
  77. 
    
  78. export function validateProperties(type, props) {
    
  79.   if (__DEV__) {
    
  80.     const invalidProps = [];
    
  81. 
    
  82.     for (const key in props) {
    
  83.       const isValid = validateProperty(type, key);
    
  84.       if (!isValid) {
    
  85.         invalidProps.push(key);
    
  86.       }
    
  87.     }
    
  88. 
    
  89.     const unknownPropString = invalidProps
    
  90.       .map(prop => '`' + prop + '`')
    
  91.       .join(', ');
    
  92. 
    
  93.     if (invalidProps.length === 1) {
    
  94.       console.error(
    
  95.         'Invalid aria prop %s on <%s> tag. ' +
    
  96.           'For details, see https://reactjs.org/link/invalid-aria-props',
    
  97.         unknownPropString,
    
  98.         type,
    
  99.       );
    
  100.     } else if (invalidProps.length > 1) {
    
  101.       console.error(
    
  102.         'Invalid aria props %s on <%s> tag. ' +
    
  103.           'For details, see https://reactjs.org/link/invalid-aria-props',
    
  104.         unknownPropString,
    
  105.         type,
    
  106.       );
    
  107.     }
    
  108.   }
    
  109. }