1
1
import { defaultCompletionIcons , defaultHoverInfoProcessor , rendererRich } from 'shikiji-twoslash'
2
2
import type { RendererRichOptions , TwoslashRenderer } from 'shikiji-twoslash'
3
- import type { Element , Text } from 'hast'
3
+ import type { NodeHover , NodeQuery } from 'twoslash'
4
+ import type { Element , ElementContent , Text } from 'hast'
4
5
import type { ShikijiTransformerContext } from 'shikiji'
5
6
import { gfmFromMarkdown } from 'mdast-util-gfm'
6
7
import { fromMarkdown } from 'mdast-util-from-markdown'
@@ -21,10 +22,9 @@ export function rendererFloatingVue(options: VitePressPluginTwoslashOptions & Re
21
22
...options ,
22
23
} )
23
24
24
- function createFloatingVueWarpper ( this : ShikijiTransformerContext , text : string , docs : string | undefined , node : Element | Text , presisted = false ) : Element | undefined {
25
- const content = processHoverInfo ( text )
26
-
27
- if ( ( ! content || content === 'any' ) )
25
+ function createFloatingVueWarpper ( this : ShikijiTransformerContext , info : NodeHover | NodeQuery , node : Element | Text , presisted = false ) : Element | undefined {
26
+ const content = processHoverInfo ( info . text )
27
+ if ( ! content || content === 'any' )
28
28
return undefined
29
29
30
30
const themedContent = ( this . codeToHast (
@@ -41,12 +41,11 @@ export function rendererFloatingVue(options: VitePressPluginTwoslashOptions & Re
41
41
addClassToHast ( node , 'twoslash-popup-type' )
42
42
} )
43
43
44
- if ( docs ) {
45
- docs = processHoverDocs ( docs ) ?? docs
46
- const mdast = fromMarkdown ( docs , {
44
+ const markdownToHast = ( md : string ) : ElementContent [ ] => {
45
+ const mdast = fromMarkdown ( md , {
47
46
mdastExtensions : [ gfmFromMarkdown ( ) ] ,
48
47
} )
49
- const hast = toHast ( mdast , {
48
+ return ( toHast ( mdast , {
50
49
handlers : {
51
50
code : ( state , node ) => {
52
51
const lang = node . lang || ''
@@ -63,14 +62,71 @@ export function rendererFloatingVue(options: VitePressPluginTwoslashOptions & Re
63
62
return defaultHandlers . code ( state , node )
64
63
} ,
65
64
} ,
66
- } )
65
+ } ) as Element ) . children
66
+ }
67
+
68
+ const markdownInlineToHast = ( md : string ) : ElementContent [ ] => {
69
+ const children = markdownToHast ( md )
70
+ if ( children . length === 1 && children [ 0 ] . type === 'element' && children [ 0 ] . tagName === 'p' )
71
+ return children [ 0 ] . children
72
+ return children
73
+ }
74
+
75
+ if ( info . docs ) {
76
+ const docs = processHoverDocs ( info . docs ) ?? info . docs
77
+ const children = markdownToHast ( docs )
78
+
67
79
themedContent . push ( {
68
80
type : 'element' ,
69
81
tagName : 'div' ,
70
82
properties : {
71
83
class : 'twoslash-popup-jsdoc vp-doc' ,
72
84
} ,
73
- children : ( hast as any ) . children ,
85
+ children,
86
+ } )
87
+ }
88
+
89
+ if ( info . tags ?. length ) {
90
+ themedContent . push ( {
91
+ type : 'element' ,
92
+ tagName : 'div' ,
93
+ properties : {
94
+ class : 'twoslash-popup-jsdoc twoslash-popup-jsdoc-tags vp-doc' ,
95
+ } ,
96
+ children : info . tags . map ( tag => ( < Element > {
97
+ type : 'element' ,
98
+ tagName : 'span' ,
99
+ properties : {
100
+ class : `twoslash-popup-jsdoc-tag` ,
101
+ } ,
102
+ children : [
103
+ {
104
+ type : 'element' ,
105
+ tagName : 'span' ,
106
+ properties : {
107
+ class : 'twoslash-popup-jsdoc-tag-name' ,
108
+ } ,
109
+ children : [
110
+ {
111
+ type : 'text' ,
112
+ value : `@${ tag [ 0 ] } ` ,
113
+ } ,
114
+ ] ,
115
+ } ,
116
+ ...tag [ 1 ]
117
+ ? [
118
+ < Element > {
119
+ type : 'element' ,
120
+ tagName : 'span' ,
121
+ properties : {
122
+ class : 'twoslash-popup-jsdoc-tag-value' ,
123
+ } ,
124
+ children : markdownInlineToHast ( tag [ 1 ] ) ,
125
+ } ,
126
+ ]
127
+ : [ ] ,
128
+ ] ,
129
+ } ) ) ,
74
130
} )
75
131
}
76
132
@@ -129,12 +185,12 @@ export function rendererFloatingVue(options: VitePressPluginTwoslashOptions & Re
129
185
return {
130
186
...rich ,
131
187
nodeStaticInfo ( info , node ) {
132
- return createFloatingVueWarpper . call ( this , info . text , info . docs , node ) || { }
188
+ return createFloatingVueWarpper . call ( this , info , node ) || { }
133
189
} ,
134
190
nodeQuery ( query , node ) {
135
191
if ( ! query . text )
136
192
return { }
137
- return createFloatingVueWarpper . call ( this , query . text , query . docs , node , true ) || { }
193
+ return createFloatingVueWarpper . call ( this , query , node , true ) || { }
138
194
} ,
139
195
nodeCompletion ( query , node ) {
140
196
if ( node . type !== 'text' )
0 commit comments