[READ-ONLY] a fast, modern browser for the npm registry
at main 164 lines 5.5 kB view raw
1<script setup lang="ts"> 2import { getOutdatedTooltip, getVersionClass } from '~/utils/npm/outdated-dependencies' 3import type { RouteLocationRaw } from 'vue-router' 4 5const props = defineProps<{ 6 packageName: string 7 version: string 8 installScripts: { 9 scripts: ('preinstall' | 'install' | 'postinstall')[] 10 content?: Record<string, string> 11 npxDependencies: Record<string, string> 12 } 13}>() 14 15function getCodeLink(filePath: string): RouteLocationRaw { 16 const split = props.packageName.split('/') 17 18 return { 19 name: 'code', 20 params: { 21 org: split.length === 2 ? split[0] : null, 22 packageName: split.length === 2 ? split[1]! : split[0]!, 23 version: props.version, 24 filePath: filePath, 25 }, 26 } 27} 28 29const scriptParts = computed(() => { 30 const parts: Record< 31 string, 32 { prefix: string | null; filePath: string | null; link: RouteLocationRaw } 33 > = {} 34 for (const scriptName of props.installScripts.scripts) { 35 const content = props.installScripts.content?.[scriptName] 36 if (!content) continue 37 const parsed = parseNodeScript(content) 38 if (parsed) { 39 parts[scriptName] = { 40 prefix: parsed.prefix, 41 filePath: parsed.filePath, 42 link: getCodeLink(parsed.filePath), 43 } 44 } else { 45 parts[scriptName] = { prefix: null, filePath: null, link: getCodeLink('package.json') } 46 } 47 } 48 return parts 49}) 50 51const outdatedNpxDeps = useOutdatedDependencies(() => props.installScripts.npxDependencies) 52const hasNpxDeps = computed(() => Object.keys(props.installScripts.npxDependencies).length > 0) 53const sortedNpxDeps = computed(() => { 54 return Object.entries(props.installScripts.npxDependencies).sort(([a], [b]) => a.localeCompare(b)) 55}) 56 57const isExpanded = shallowRef(false) 58</script> 59 60<template> 61 <CollapsibleSection 62 :title="$t('package.install_scripts.title')" 63 id="installScripts" 64 icon="i-lucide:circle-alert w-3 h-3 text-yellow-500" 65 > 66 <!-- Script list: name as label, content below --> 67 <dl class="space-y-2 m-0"> 68 <div v-for="scriptName in installScripts.scripts" :key="scriptName"> 69 <dt class="font-mono text-xs text-fg-muted">{{ scriptName }}</dt> 70 <dd 71 class="font-mono text-sm text-fg-subtle m-0 truncate" 72 :title="installScripts.content?.[scriptName]" 73 > 74 <template v-if="installScripts.content?.[scriptName] && scriptParts[scriptName]"> 75 <template v-if="scriptParts[scriptName].prefix"> 76 {{ scriptParts[scriptName].prefix 77 }}<LinkBase :to="scriptParts[scriptName].link">{{ 78 scriptParts[scriptName].filePath 79 }}</LinkBase> 80 </template> 81 <LinkBase v-else :to="scriptParts[scriptName].link"> 82 {{ installScripts.content[scriptName] }} 83 </LinkBase> 84 </template> 85 <span v-else tabindex="0" class="cursor-help"> 86 {{ $t('package.install_scripts.script_label') }} 87 </span> 88 </dd> 89 </div> 90 </dl> 91 92 <!-- npx packages (expandable) --> 93 <div v-if="hasNpxDeps" class="mt-3"> 94 <button 95 type="button" 96 class="flex items-center gap-1.5 text-xs text-fg-muted hover:text-fg transition-colors duration-200 focus-visible:outline-accent/70 rounded" 97 :aria-expanded="isExpanded" 98 aria-controls="npx-packages-details" 99 @click="isExpanded = !isExpanded" 100 > 101 <span 102 class="i-lucide:chevron-right rtl-flip w-3 h-3 transition-transform duration-200" 103 :class="{ 'rotate-90': isExpanded }" 104 aria-hidden="true" 105 /> 106 {{ 107 $t( 108 'package.install_scripts.npx_packages', 109 { count: sortedNpxDeps.length }, 110 sortedNpxDeps.length, 111 ) 112 }} 113 </button> 114 115 <ul 116 v-show="isExpanded" 117 id="npx-packages-details" 118 class="mt-2 space-y-1 list-none m-0 p-0 ps-4" 119 > 120 <li 121 v-for="[dep, version] in sortedNpxDeps" 122 :key="dep" 123 class="flex items-center justify-between py-0.5 text-sm gap-2" 124 > 125 <LinkBase 126 :to="packageRoute(dep)" 127 class="font-mono text-fg-muted hover:text-fg transition-colors duration-200 truncate min-w-0" 128 > 129 {{ dep }} 130 </LinkBase> 131 <span class="flex items-center gap-1"> 132 <TooltipApp 133 v-if=" 134 outdatedNpxDeps[dep] && 135 outdatedNpxDeps[dep].resolved !== outdatedNpxDeps[dep].latest 136 " 137 class="shrink-0 p-2 -m-2" 138 :class="getVersionClass(outdatedNpxDeps[dep])" 139 aria-hidden="true" 140 :text="getOutdatedTooltip(outdatedNpxDeps[dep], $t)" 141 > 142 <span class="i-lucide:circle-alert w-3 h-3" /> 143 </TooltipApp> 144 <span 145 class="font-mono text-xs text-end truncate" 146 :class="getVersionClass(outdatedNpxDeps[dep])" 147 :title=" 148 outdatedNpxDeps[dep] 149 ? outdatedNpxDeps[dep].resolved === outdatedNpxDeps[dep].latest 150 ? $t('package.install_scripts.currently', { 151 version: outdatedNpxDeps[dep].latest, 152 }) 153 : getOutdatedTooltip(outdatedNpxDeps[dep], $t) 154 : version 155 " 156 > 157 {{ version }} 158 </span> 159 </span> 160 </li> 161 </ul> 162 </div> 163 </CollapsibleSection> 164</template>