diff --git a/source/NVDAObjects/IAccessible/ia2Web.py b/source/NVDAObjects/IAccessible/ia2Web.py index 50a7103a819..84abe4fde0c 100644 --- a/source/NVDAObjects/IAccessible/ia2Web.py +++ b/source/NVDAObjects/IAccessible/ia2Web.py @@ -213,8 +213,30 @@ def _get_states(self): if popupState: states.discard(controlTypes.State.HASPOPUP) states.add(popupState) + if self.isInternalLink: + states.add(controlTypes.State.INTERNAL_LINK) return states + @property + def isInternalLink(self) -> bool: + if self.role != controlTypes.Role.LINK: + return False + if ( + not hasattr(self, "treeInterceptor") + or self.treeInterceptor is None + or not self.treeInterceptor.documentConstantIdentifier + ): + return False + documentConstantIdentifier = self.treeInterceptor.documentConstantIdentifier + if documentConstantIdentifier.endswith("/"): + documentConstantIdentifier = documentConstantIdentifier[:-1] + queryParamCharPos = documentConstantIdentifier.find("?") + if queryParamCharPos > 0: + documentConstantIdentifier = documentConstantIdentifier[:queryParamCharPos] + if self.value.startswith(f"{documentConstantIdentifier}#"): + return True + return False + def _get_landmark(self): xmlRoles = self.IA2Attributes.get("xml-roles", "").split(" ") landmark = next((xr for xr in xmlRoles if xr in aria.landmarkRoles), None) diff --git a/source/controlTypes/state.py b/source/controlTypes/state.py index affc16b3550..ef26f0ef653 100644 --- a/source/controlTypes/state.py +++ b/source/controlTypes/state.py @@ -102,6 +102,7 @@ def negativeDisplayString(self) -> str: HASPOPUP_GRID = setBit(48) HASPOPUP_LIST = setBit(49) HASPOPUP_TREE = setBit(50) + INTERNAL_LINK = setBit(51) STATES_SORTED = frozenset([State.SORTED, State.SORTED_ASCENDING, State.SORTED_DESCENDING]) @@ -204,6 +205,9 @@ def negativeDisplayString(self) -> str: State.HASPOPUP_LIST: _("opens list"), # Translators: Presented when a control has a pop-up tree. State.HASPOPUP_TREE: _("opens tree"), + # Translators: Presented when a link destination points to the page containing the link. + # For example, links of a table of contents of a document with different sections. + State.INTERNAL_LINK: _("same page"), }