1- import { visit } from 'unist-util-visit'
2- import type { Root , Element , ElementContent , Text } from 'hast'
1+ import { SKIP , visit } from 'unist-util-visit'
2+ import type { Root , Element , ElementContent , Text , Properties } from 'hast'
33
44const FOOTNOTES_HEADING_TEXT = 'Footnotes'
55const FOOTNOTES_HEADING_ID = 'footnote-label'
6+ const TOOLTIP_HOST_CLASSES = [ 'relative' , 'inline-flex' ]
7+ const TOOLTIP_TRIGGER_CLASSES = [
8+ 'inline-flex' ,
9+ 'items-center' ,
10+ 'focus-visible:outline-2' ,
11+ 'focus-visible:outline-offset-2' ,
12+ 'focus-visible:outline-spotlight' ,
13+ ]
14+ const TOOLTIP_POPUP_CLASSES = [
15+ 'pointer-events-none' ,
16+ 'absolute' ,
17+ 'left-0' ,
18+ 'top-full' ,
19+ 'z-(--z-content-floating)' ,
20+ 'mt-2' ,
21+ 'hidden' ,
22+ 'max-w-64' ,
23+ 'rounded-md' ,
24+ 'border' ,
25+ 'border-trim' ,
26+ 'bg-page-inverse' ,
27+ 'px-2' ,
28+ 'py-1' ,
29+ 'text-sm' ,
30+ 'leading-tight' ,
31+ 'text-page-base' ,
32+ 'shadow-elevated' ,
33+ 'whitespace-nowrap' ,
34+ ]
635
736function isElementNode ( node : ElementContent ) : node is Element {
837 return node . type === 'element'
@@ -86,6 +115,49 @@ function buildTitle(template: string, identifier: string): string {
86115 return template . includes ( '$id' ) ? template . replaceAll ( '$id' , identifier ) : template
87116}
88117
118+ function removeTooltipProperties ( properties : Properties ) : Properties {
119+ const nextProperties : Properties = { ...properties }
120+ delete nextProperties [ 'data-tooltip' ]
121+ delete nextProperties [ 'title' ]
122+ return nextProperties
123+ }
124+
125+ function wrapBackrefWithTooltip ( node : Element , title : string ) : void {
126+ const anchorNode : Element = {
127+ type : 'element' ,
128+ tagName : 'a' ,
129+ properties : removeTooltipProperties ( node . properties || { } ) ,
130+ children : node . children ,
131+ }
132+
133+ node . tagName = 'site-tooltip'
134+ node . properties = {
135+ className : TOOLTIP_HOST_CLASSES ,
136+ }
137+ node . children = [
138+ {
139+ type : 'element' ,
140+ tagName : 'span' ,
141+ properties : {
142+ 'data-tooltip-trigger' : '' ,
143+ className : TOOLTIP_TRIGGER_CLASSES ,
144+ } ,
145+ children : [ anchorNode ] ,
146+ } ,
147+ {
148+ type : 'element' ,
149+ tagName : 'span' ,
150+ properties : {
151+ 'data-tooltip-popup' : '' ,
152+ role : 'tooltip' ,
153+ 'aria-hidden' : 'true' ,
154+ className : TOOLTIP_POPUP_CLASSES ,
155+ } ,
156+ children : [ { type : 'text' , value : title } ] ,
157+ } ,
158+ ]
159+ }
160+
89161export type RehypeFootnotesTitleOptions = string
90162
91163export function rehypeFootnotesTitle ( titleTemplate : RehypeFootnotesTitleOptions = '' ) {
@@ -110,8 +182,8 @@ export function rehypeFootnotesTitle(titleTemplate: RehypeFootnotesTitleOptions
110182 const identifier = getIdentifierFromBackrefHref ( properties [ 'href' ] )
111183 if ( ! identifier ) return
112184
113- properties [ 'title' ] = buildTitle ( titleTemplate , identifier )
114- node . properties = properties
185+ wrapBackrefWithTooltip ( node , buildTitle ( titleTemplate , identifier ) )
186+ return SKIP
115187 } )
116188 }
117189}
0 commit comments