Skip to content

Commit 112e438

Browse files
authored
Merge pull request #982 from teleporthq/attr-transfer-ability-node
Transfer anchor safe attrs to wrapping anchor tag when a node has a l…
2 parents e8ab730 + 1a7153b commit 112e438

File tree

1 file changed

+57
-0
lines changed
  • packages/teleport-uidl-resolver/src/resolvers/abilities

1 file changed

+57
-0
lines changed

packages/teleport-uidl-resolver/src/resolvers/abilities/utils.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,42 @@ import {
66
UIDLAttributeValue,
77
} from '@teleporthq/teleport-types'
88

9+
// Whitelist of attributes that are safe to transfer to anchor tags
10+
const ANCHOR_SAFE_ATTRIBUTES = new Set([
11+
// Standard HTML attributes
12+
'class',
13+
'id',
14+
'style',
15+
'title',
16+
'lang',
17+
'dir',
18+
'tabindex',
19+
'accesskey',
20+
'contenteditable',
21+
'draggable',
22+
'hidden',
23+
'spellcheck',
24+
'translate',
25+
])
26+
27+
// ARIA attributes safe for anchor tags (link-specific)
28+
const ANCHOR_SAFE_ARIA_ATTRIBUTES = new Set([
29+
'aria-describedby', // Describes the link purpose (valid transfer)
30+
'aria-labelledby', // References label for the link
31+
'aria-expanded', // For dropdown/collapsible links
32+
'aria-haspopup', // For links that open menus/dialogs
33+
'aria-current', // For navigation state
34+
'aria-disabled', // For disabled links
35+
])
36+
37+
const isAttributeSafeForAnchor = (attrName: string): boolean => {
38+
return (
39+
ANCHOR_SAFE_ATTRIBUTES.has(attrName) ||
40+
attrName.startsWith('data-') ||
41+
ANCHOR_SAFE_ARIA_ATTRIBUTES.has(attrName)
42+
)
43+
}
44+
945
export const insertLinks = (
1046
node: UIDLElementNode,
1147
options: GeneratorOptions,
@@ -149,6 +185,27 @@ export const insertLinks = (
149185
}
150186

151187
const linkNode = createLinkNode(abilities.link, options)
188+
189+
if (node.type === 'element' && node.content.attrs) {
190+
// Filter attributes to only transfer those safe for anchor tags
191+
const safeAttrs: Record<string, UIDLAttributeValue> = {}
192+
Object.keys(node.content.attrs).forEach((attrName) => {
193+
if (isAttributeSafeForAnchor(attrName)) {
194+
safeAttrs[attrName] = { ...node.content.attrs[attrName] }
195+
}
196+
})
197+
198+
linkNode.content.attrs = {
199+
...linkNode.content.attrs,
200+
...safeAttrs,
201+
}
202+
203+
// Remove only the transferred attributes from the original node
204+
Object.keys(safeAttrs).forEach((attrName) => {
205+
delete node.content.attrs[attrName]
206+
})
207+
}
208+
152209
linkNode.content.children.push(node)
153210

154211
if (parentNode === undefined || parentNode?.content.style?.display?.content === 'flex') {

0 commit comments

Comments
 (0)