@@ -3,25 +3,42 @@ import { onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client'
3
3
import { registry } from ' ../src/registry'
4
4
import { devtools , getScriptSize , humanFriendlyTimestamp , reactive , ref , urlToOrigin } from ' #imports'
5
5
import { loadShiki } from ' ~/composables/shiki'
6
+ import { msToHumanReadable } from ' ~/utils/formatting'
6
7
7
8
const scriptRegistry = registry (s => s )
8
9
await loadShiki ()
9
10
10
11
const scripts = ref ({})
11
- const scriptSizes = reactive ({})
12
+ const scriptSizes = reactive < Record < string , string >> ({})
12
13
13
14
function syncScripts(_scripts : any []) {
14
- scripts .value = { ... _scripts }
15
- // check if the script size has been set, if not set it
16
- for (const key in _scripts ) {
17
- if (! scriptSizes [key ]) {
18
- getScriptSize (_scripts [key ].src ).then ((size ) => {
19
- scriptSizes [key ] = size
20
- }).catch (() => {
21
- scriptSizes [key ] = 0
22
- })
23
- }
24
- }
15
+ // augment the scripts with registry
16
+ scripts .value = Object .fromEntries (
17
+ Object .entries ({ ... _scripts })
18
+ .map (([key , script ]) => {
19
+ script .registry = scriptRegistry .find (s => titleToCamelCase (s .label ) === script .registryKey )
20
+ if (script .registry ) {
21
+ const kebabCaseLabel = script .registry .label .toLowerCase ().replace (/ / g , ' -' )
22
+ script .docs = ` https://scripts.nuxt.com/scripts/${script .registry .category }/${kebabCaseLabel } `
23
+ }
24
+ const loadingAt = script .events .find (e => e .status === ' loading' )?.at || 0
25
+ const loadedAt = script .events .find (e => e .status === ' loaded' )?.at || 0
26
+ if (loadingAt && loadedAt ) {
27
+ script .loadTime = msToHumanReadable (loadedAt - loadingAt )
28
+ }
29
+ const scriptSizeKey = script .src
30
+ if (! scriptSizes [scriptSizeKey ]) {
31
+ getScriptSize (script .src ).then ((size ) => {
32
+ scriptSizes [scriptSizeKey ] = size
33
+ script .size = size
34
+ }).catch (() => {
35
+ script .size = ' '
36
+ scriptSizes [scriptSizeKey ] = ' '
37
+ })
38
+ }
39
+ return [key , script ]
40
+ }),
41
+ )
25
42
}
26
43
27
44
function titleToCamelCase(s : string ) {
@@ -31,9 +48,7 @@ function titleToCamelCase(s: string) {
31
48
return w .charAt (0 ).toUpperCase () + w .slice (1 ).toLowerCase ()
32
49
}).join (' ' )
33
50
}
34
- function resolveScriptRegistry(id : string ) {
35
- return scriptRegistry .find (s => titleToCamelCase (s .label ) === id )
36
- }
51
+
37
52
const version = ref (null )
38
53
onDevtoolsClientConnected (async (client ) => {
39
54
devtools .value = client .devtools
@@ -44,6 +59,16 @@ onDevtoolsClientConnected(async (client) => {
44
59
syncScripts (client .host .nuxt ._scripts )
45
60
})
46
61
const tab = ref (' scripts' )
62
+
63
+ function viewDocs(docs : string ) {
64
+ tab .value = ' docs'
65
+ setTimeout (() => {
66
+ const iframe = document .querySelector (' iframe' )
67
+ if (iframe ) {
68
+ iframe .src = docs
69
+ }
70
+ }, 100 )
71
+ }
47
72
</script >
48
73
49
74
<template >
@@ -116,14 +141,6 @@ const tab = ref('scripts')
116
141
>
117
142
</label >
118
143
</fieldset >
119
- <!-- <VTooltip> -->
120
- <!-- <button text-lg="" type="button" class="n-icon-button n-button n-transition n-disabled:n-disabled"> -->
121
- <!-- <NIcon icon="carbon:reset" class="group-hover:text-green-500" /> -->
122
- <!-- </button> -->
123
- <!-- <template #popper> -->
124
- <!-- Refresh -->
125
- <!-- </template> -->
126
- <!-- </VTooltip> -->
127
144
</div >
128
145
<div class =" items-center space-x-3 hidden lg:flex" >
129
146
<div class =" opacity-80 text-sm" >
@@ -147,19 +164,49 @@ const tab = ref('scripts')
147
164
<div class =" space-y-3" >
148
165
<OSectionBlock v-for =" (script, id) in scripts" :key =" id" class =" w-full" >
149
166
<template #text >
150
- <div class =" flex items-center justify-between w-full" >
151
- <div class =" flex items-center gap-4 " >
152
- <a class =" text-lg font-bold flex gap-2 items-center font-mono " :title = " script.src " target = " _blank " :href = " script.src " >
153
- <div v-if =" resolveScriptRegistry(id) " class =" flex items-center max-w-10 h-6" v-html =" resolveScriptRegistry(id) .logo" />
167
+ <div class =" flex items-center justify-between w-full gap-7 " >
168
+ <div class =" flex items-center gap-7 " >
169
+ <div class =" flex items-center gap-1 " >
170
+ <div v-if =" script.registry " class =" flex items-center max-w-6 h-6" v-html =" script.registry .logo" />
154
171
<img v-else-if =" !script.src.startsWith('/')" :src =" `https://www.google.com/s2/favicons?domain=${urlToOrigin(script.src)}`" class =" w-4 h-4 rounded-lg" >
155
- <div >{{ resolveScriptRegistry(id)?.label || script.key }}</div >
156
- </a >
157
- <div class =" opacity-70" >
172
+ <div >
173
+ <a title =" View script source" class =" text-base hover:bg-gray-800/50 px-2 transition py-1 rounded-xl font-semibold flex gap-2 items-center" target =" _blank" :href =" script.src" >
174
+ <div >
175
+ {{ script.registry?.label || script.key }}
176
+ </div >
177
+ </a >
178
+ <div class =" flex flex-items-center gap-3" >
179
+ <template v-if =" script .docs " >
180
+ <button type =" button" class =" ml-2 opacity-50 hover:opacity-70 transition ml-1 text-xs underline" @click =" viewDocs(script.docs)" >
181
+ View docs
182
+ </button >
183
+ </template >
184
+ <div v-for =" k in Object.keys(script.registryMeta)" :key =" k" class =" text-xs text-gray-500" >
185
+ <span class =" capitalize" >{{ k }}</span >: {{ script.registryMeta[k] }}
186
+ </div >
187
+ </div >
188
+ </div >
189
+ </div >
190
+ </div >
191
+ <div >
192
+ <div class =" opacity-70 text-xs" >
193
+ Status
194
+ </div >
195
+ <div class =" capitalize" >
158
196
{{ script.$script.status.value }}
159
197
</div >
160
- <div v-if =" scriptSizes[script.key]" >
161
- {{ scriptSizes[script.key] }}
198
+ </div >
199
+ <div v-if =" scriptSizes[script.src]" >
200
+ <div class =" opacity-70 text-xs" >
201
+ Size
202
+ </div >
203
+ <div >{{ scriptSizes[script.src] }}</div >
204
+ </div >
205
+ <div v-if =" script.loadTime" >
206
+ <div class =" opacity-70 text-xs" >
207
+ Time to loaded
162
208
</div >
209
+ <div >{{ script.loadTime }}</div >
163
210
</div >
164
211
<div >
165
212
<NButton v-if =" script.$script.status === 'awaitingLoad'" @click =" script.$script.load()" >
0 commit comments