22import type { TreeNodeInput } from ' nanovis'
33import type { PluginBuildInfo , RolldownPluginBuildMetrics , SessionContext } from ' ~~/shared/types'
44import { Flamegraph , normalizeTreeNode } from ' nanovis'
5- import { relative } from ' pathe'
65import { computed , onMounted , onUnmounted , ref , shallowRef , useTemplateRef , watch } from ' vue'
76import { parseReadablePath } from ' ~/utils/filepath'
87import { normalizeTimestamp } from ' ~/utils/format'
@@ -26,51 +25,41 @@ const moduleTypes = computed(() => ModuleTypeRules.filter(rule => parsedPaths.va
2625
2726const n = (node : TreeNodeInput <PluginBuildInfo >) => normalizeTreeNode (node , undefined , false )
2827
29- function normalizeModulePath(path : string ) {
30- const normalized = path .replace (/ %2F/ g , ' /' )
31- const cwd = props .session ! .meta .cwd
32- let relate = cwd ? relative (cwd , normalized ) : normalized
33- if (! relate .startsWith (' .' ))
34- relate = ` ./${relate } `
35- if (relate .startsWith (' ./' ))
36- return relate
37- if (relate .match (/ ^ (?:\.\.\/ ){1,3} [^ . ] / ))
38- return relate
39- return normalized
40- }
41-
4228const tree = computed (() => {
4329 const resolveIds = moduleTypes .value .map ((type , idx ) => n ({
4430 id: ` resolveId-${type .name }-${idx } ` ,
4531 text: type .description ,
4632 children: props .buildMetrics .resolveIdMetrics .filter ((item ) => {
4733 return getFileTypeFromModuleId (item .module ).name === type .name
48- }).map ((id , idx ) => n ({
34+ }).map ((item , idx ) => n ({
4935 id: ` resolveId-${idx } ` ,
50- text: normalizeModulePath (id .module ),
51- size: id .duration ,
36+ text: item .module ,
37+ size: item .duration ,
38+ meta: item ,
5239 })),
5340 }))
5441 const loads = moduleTypes .value .map ((type , idx ) => n ({
5542 id: ` loads-${type .name }-${idx } ` ,
5643 text: type .description ,
5744 children: props .buildMetrics .loadMetrics .filter ((item ) => {
5845 return getFileTypeFromModuleId (item .module ).name === type .name
59- }).map ((id , idx ) => n ({
46+ }).map ((item , idx ) => n ({
6047 id: ` resolveId-${idx } ` ,
61- text: normalizeModulePath (id .module ),
62- size: id .duration ,
48+ text: item .module ,
49+ size: item .duration ,
50+ meta: item ,
6351 })),
6452 }))
6553 const transforms = moduleTypes .value .map ((type , idx ) => n ({
6654 id: ` transforms-${type .name }-${idx } ` ,
6755 text: type .description ,
6856 children: props .buildMetrics .transformMetrics .filter ((item ) => {
6957 return getFileTypeFromModuleId (item .module ).name === type .name
70- }).map ((id , idx ) => n ({
58+ }).map ((item , idx ) => n ({
7159 id: ` resolveId-${idx } ` ,
72- text: normalizeModulePath (id .module ),
73- size: id .duration ,
60+ text: item .module ,
61+ size: item .duration ,
62+ meta: item ,
7463 })),
7564 }))
7665
@@ -101,7 +90,7 @@ const tree = computed(() => {
10190})
10291
10392const hoverNode = ref <{
104- plugin_name : string
93+ title : string
10594 duration: number
10695 meta: PluginBuildInfo | undefined
10796} | null >(null )
@@ -133,7 +122,7 @@ function buildFlamegraph() {
133122 hoverY .value = e .clientY
134123 }
135124 hoverNode .value = {
136- plugin_name : node .text ! ,
125+ title : node .text ! ,
137126 duration: node .size ,
138127 meta: node .meta ,
139128 }
@@ -167,26 +156,45 @@ watch(tree, async () => {
167156 <Teleport to =" body" >
168157 <div
169158 v-if =" hoverNode"
170- border =" ~ base" rounded shadow px2 py1 fixed
171- z-panel-content bg-glass pointer-events-none text-sm
159+ border =" ~ base" rounded-lg shadow-lg px3 py2 fixed
160+ z-panel-content bg-glass pointer-events-none text-sm max-w-80
172161 :style =" { left: `${hoverX}px`, top: `${hoverY}px` }"
173162 >
174- <div flex =" ~" font-bold font-mono >
175- <DisplayFileIcon v-if =" hoverNode.meta" :filename =" hoverNode.meta.module" mr1.5 />
176- {{ hoverNode.plugin_name }}
163+ <div v-if =" hoverNode.meta?.module" flex =" ~" font-semibold font-mono text-base mb2 >
164+ <DisplayModuleId :id =" hoverNode.meta.module" :session =" session" :link =" false" />
177165 </div >
178- <div v-if =" hoverNode.meta" >
179- <div >
180- <label >Start Time: </label >
181- <time :datetime =" new Date(hoverNode.meta.timestamp_start).toISOString()" >{{ normalizeTimestamp(hoverNode.meta.timestamp_start) }}</time >
166+ <div v-else font-semibold text-base mb2 >
167+ {{ hoverNode.title }}
168+ </div >
169+ <div v-if =" hoverNode.meta?.module" border =" t base" pt2 flex =" ~ col gap-1.5" min-w-48 >
170+ <div flex =" ~ justify-between items-center" py1 >
171+ <label text-xs opacity-70 >Start Time</label >
172+ <time
173+ :datetime =" new Date(hoverNode.meta.timestamp_start).toISOString()"
174+ font-mono text =" xs"
175+ bg =" base/10"
176+ px1.5 py0.5 rounded
177+ >
178+ {{ normalizeTimestamp(hoverNode.meta.timestamp_start) }}
179+ </time >
180+ </div >
181+ <div flex =" ~ justify-between items-center" py1 >
182+ <label text-xs opacity-70 >End Time</label >
183+ <time
184+ :datetime =" new Date(hoverNode.meta.timestamp_end).toISOString()"
185+ font-mono text =" xs"
186+ bg =" base/10"
187+ px1.5 py0.5 rounded
188+ >
189+ {{ normalizeTimestamp(hoverNode.meta.timestamp_end) }}
190+ </time >
182191 </div >
183- <div >
184- <label >End Time: </label >
185- <time :datetime = " new Date( hoverNode.meta.timestamp_end).toISOString() " >{{ normalizeTimestamp(hoverNode.meta.timestamp_end) }}</ time >
192+ <div flex = " ~ justify-between items-center " py1 border = " t base dashed " pt2 >
193+ <label text = " xs " op70 >Duration </label >
194+ <DisplayDuration :duration = " hoverNode.duration " / >
186195 </div >
187196 </div >
188- <div flex =" ~ gap-1" >
189- <label >Duration: </label >
197+ <div v-else >
190198 <DisplayDuration :duration =" hoverNode.duration" />
191199 </div >
192200 </div >
0 commit comments