[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: move readme click overriding to readme component (#681)

Co-authored-by: Daniel Roe <daniel@roe.dev>

authored by

Garth de Wet
Daniel Roe
and committed by
GitHub
1a48cfe4 b0a0bd4f

+44 -37
+43 -18
app/components/Readme.vue
··· 3 3 html: string 4 4 }>() 5 5 6 + const router = useRouter() 6 7 const { copy } = useClipboard() 7 8 8 - const handleCopy = async (e: MouseEvent) => { 9 - const target = (e.target as HTMLElement).closest('[data-copy]') 9 + // Combined click handler for: 10 + // 1. Intercepting npmjs.com links to route internally 11 + // 2. Copy button functionality for code blocks 12 + function handleClick(event: MouseEvent) { 13 + const target = event.target as HTMLElement | undefined 10 14 if (!target) return 11 15 12 - const wrapper = target.closest('.readme-code-block') 13 - if (!wrapper) return 16 + // Handle copy button clicks 17 + const copyTarget = target.closest('[data-copy]') 18 + if (copyTarget) { 19 + const wrapper = copyTarget.closest('.readme-code-block') 20 + if (!wrapper) return 21 + 22 + const pre = wrapper.querySelector('pre') 23 + if (!pre?.textContent) return 24 + 25 + copy(pre.textContent) 26 + 27 + const icon = copyTarget.querySelector('span') 28 + if (!icon) return 29 + 30 + const originalIcon = 'i-carbon:copy' 31 + const successIcon = 'i-carbon:checkmark' 14 32 15 - const pre = wrapper.querySelector('pre') 16 - if (!pre?.textContent) return 33 + icon.classList.remove(originalIcon) 34 + icon.classList.add(successIcon) 17 35 18 - await copy(pre.textContent) 36 + setTimeout(() => { 37 + icon.classList.remove(successIcon) 38 + icon.classList.add(originalIcon) 39 + }, 2000) 40 + return 41 + } 19 42 20 - const icon = target.querySelector('span') 21 - if (!icon) return 43 + // Handle npmjs.com link clicks - route internally 44 + const anchor = target.closest('a') 45 + if (!anchor) return 22 46 23 - const originalIcon = 'i-carbon:copy' 24 - const successIcon = 'i-carbon:checkmark' 47 + const href = anchor.getAttribute('href') 48 + if (!href) return 25 49 26 - icon.classList.remove(originalIcon) 27 - icon.classList.add(successIcon) 50 + const match = href.match(/^(?:https?:\/\/)?(?:www\.)?npmjs\.(?:com|org)(\/.+)$/) 51 + if (!match || !match[1]) return 28 52 29 - setTimeout(() => { 30 - icon.classList.remove(successIcon) 31 - icon.classList.add(originalIcon) 32 - }, 2000) 53 + const route = router.resolve(match[1]) 54 + if (route) { 55 + event.preventDefault() 56 + router.push(route) 57 + } 33 58 } 34 59 </script> 35 60 ··· 37 62 <article 38 63 class="readme prose prose-invert max-w-[70ch] lg:max-w-none" 39 64 v-html="html" 40 - @click="handleCopy" 65 + @click="handleClick" 41 66 /> 42 67 </template> 43 68
+1 -19
app/pages/package/[...package].vue
··· 385 385 stars: () => stars.value ?? 0, 386 386 primaryColor: '#60a5fa', 387 387 }) 388 - 389 - // We're using only @click because it catches touch events and enter hits 390 - function handleClick(event: MouseEvent) { 391 - const target = (event?.target as HTMLElement | undefined)?.closest('a') 392 - if (!target) return 393 - 394 - const href = target.getAttribute('href') 395 - if (!href) return 396 - 397 - const match = href.match(/^(?:https?:\/\/)?(?:www\.)?npmjs\.(?:com|org)(\/.+)$/) 398 - if (!match || !match[1]) return 399 - 400 - const route = router.resolve(match[1]) 401 - if (route) { 402 - event.preventDefault() 403 - router.push(route) 404 - } 405 - } 406 388 </script> 407 389 408 390 <template> ··· 979 961 </a> 980 962 </h2> 981 963 <!-- eslint-disable vue/no-v-html -- HTML is sanitized server-side --> 982 - <Readme v-if="readmeData?.html" :html="readmeData.html" @click="handleClick" /> 964 + <Readme v-if="readmeData?.html" :html="readmeData.html" /> 983 965 <p v-else class="text-fg-subtle italic"> 984 966 {{ $t('package.readme.no_readme') }} 985 967 <a