@skippr/live-agent-sdk 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1800,7 +1800,47 @@ function isActionBlocked(element) {
1800
1800
  function escapeAttributeValue(value) {
1801
1801
  return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/[\r\n]+/g, " ");
1802
1802
  }
1803
- function extractAttrs(element, role) {
1803
+ var GENERIC_ICON_NAMES = new Set(["icon", "icons", "image", "img", "sprite", "sprites", "asset"]);
1804
+ function sanitizeIconName(src) {
1805
+ if (!src || src.startsWith("data:"))
1806
+ return null;
1807
+ const withoutQuery = src.split(/[?#]/)[0] ?? "";
1808
+ const basename = withoutQuery.slice(withoutQuery.lastIndexOf("/") + 1);
1809
+ const core = basename.split(".")[0] ?? "";
1810
+ const cleaned = core.replace(/^(?:icon[-_]?|ic[-_]|svg[-_])/i, "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase().replace(/\s*\bicons?$/, "").trim();
1811
+ if (!cleaned)
1812
+ return null;
1813
+ if (/^[0-9a-f]{8,}$/i.test(cleaned))
1814
+ return null;
1815
+ if (/^\d+$/.test(cleaned))
1816
+ return null;
1817
+ if (GENERIC_ICON_NAMES.has(cleaned))
1818
+ return null;
1819
+ if (cleaned.split(" ").length > 3)
1820
+ return null;
1821
+ return cleaned.slice(0, NAME_MAX_CHARS);
1822
+ }
1823
+ function hasInteractiveAncestorWithin(image, boundary) {
1824
+ let node = image.parentElement;
1825
+ while (node && node !== boundary) {
1826
+ if (isInteractive(node, inferRole(node)))
1827
+ return true;
1828
+ node = node.parentElement;
1829
+ }
1830
+ return false;
1831
+ }
1832
+ function iconNameHint(element) {
1833
+ if (element.tagName === "IMG") {
1834
+ return sanitizeIconName(element.getAttribute("src") || "");
1835
+ }
1836
+ const image = element.querySelector("img[src]");
1837
+ if (!image)
1838
+ return null;
1839
+ if (hasInteractiveAncestorWithin(image, element))
1840
+ return null;
1841
+ return sanitizeIconName(image.getAttribute("src") || "");
1842
+ }
1843
+ function extractAttrs(element, role, name) {
1804
1844
  const attributes = [];
1805
1845
  if (role === "link") {
1806
1846
  const href = element.getAttribute("href");
@@ -1884,6 +1924,11 @@ function extractAttrs(element, role) {
1884
1924
  if (/\.gif(\?|$)/i.test(imageSrc))
1885
1925
  attributes.push("animated");
1886
1926
  }
1927
+ if (!name && isInteractive(element, role)) {
1928
+ const hint = iconNameHint(element);
1929
+ if (hint)
1930
+ attributes.push(`iconName="${escapeAttributeValue(hint)}"`);
1931
+ }
1887
1932
  if (isScrollableContainer(element, role))
1888
1933
  attributes.push("scrollable");
1889
1934
  const isNativelyDisabled = "disabled" in element && element.disabled === true;
@@ -1943,12 +1988,13 @@ function walkAndCollect(element, depth, entries) {
1943
1988
  let childDepth = depth;
1944
1989
  if (isVisibleAndEmittable && role) {
1945
1990
  const ref = ensureStableRef(element);
1991
+ const name = accessibleName(element);
1946
1992
  entries.push({
1947
1993
  depth,
1948
1994
  role,
1949
- name: accessibleName(element),
1995
+ name,
1950
1996
  ref,
1951
- attrs: extractAttrs(element, role),
1997
+ attrs: extractAttrs(element, role, name),
1952
1998
  area: rect.width * rect.height
1953
1999
  });
1954
2000
  childDepth = depth + 1;