getAccessibleChildText.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports["default"] = getAccessibleChildText;
  7. var _jsxAstUtils = require("jsx-ast-utils");
  8. var _isHiddenFromScreenReader = _interopRequireDefault(require("./isHiddenFromScreenReader"));
  9. /**
  10. * Returns a new "standardized" string: all whitespace is collapsed to one space,
  11. * and the string is lowercase
  12. * @param {string} input
  13. * @returns lowercase, single-spaced, punctuation-stripped, trimmed string
  14. */
  15. function standardizeSpaceAndCase(input) {
  16. return input.trim().replace(/[,.?¿!‽¡;:]/g, '') // strip punctuation
  17. .replace(/\s\s+/g, ' ') // collapse spaces
  18. .toLowerCase();
  19. }
  20. /**
  21. * Returns the (recursively-defined) accessible child text of a node, which (in-order) is:
  22. * 1. The element's aria-label
  23. * 2. If the element is a direct literal, the literal value
  24. * 3. Otherwise, merge all of its children
  25. * @param {JSXElement} node - node to traverse
  26. * @returns child text as a string
  27. */
  28. function getAccessibleChildText(node, elementType) {
  29. var ariaLabel = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.openingElement.attributes, 'aria-label'));
  30. // early escape-hatch when aria-label is applied
  31. if (ariaLabel) return standardizeSpaceAndCase(ariaLabel);
  32. // early-return if alt prop exists and is an image
  33. var altTag = (0, _jsxAstUtils.getLiteralPropValue)((0, _jsxAstUtils.getProp)(node.openingElement.attributes, 'alt'));
  34. if (elementType(node.openingElement) === 'img' && altTag) return standardizeSpaceAndCase(altTag);
  35. // skip if aria-hidden is true
  36. if ((0, _isHiddenFromScreenReader["default"])(elementType(node.openingElement), node.openingElement.attributes)) {
  37. return '';
  38. }
  39. var rawChildText = node.children.map(function (currentNode) {
  40. // $FlowFixMe JSXText is missing in ast-types-flow
  41. if (currentNode.type === 'Literal' || currentNode.type === 'JSXText') {
  42. return String(currentNode.value);
  43. }
  44. if (currentNode.type === 'JSXElement') {
  45. return getAccessibleChildText(currentNode, elementType);
  46. }
  47. return '';
  48. }).join(' ');
  49. return standardizeSpaceAndCase(rawChildText);
  50. }
  51. module.exports = exports.default;