Skip to content

Commit 3047a0e

Browse files
authored
Merge branch 'main' into accessible-accent
2 parents cf11cf6 + 1a48cfe commit 3047a0e

49 files changed

Lines changed: 310 additions & 274 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/components/ColumnPicker.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const columnLabelKey: Record<string, string> = {
4242
version: 'filters.columns.version',
4343
description: 'filters.columns.description',
4444
downloads: 'filters.columns.downloads',
45-
updated: 'filters.columns.updated',
45+
updated: 'filters.columns.published',
4646
maintainers: 'filters.columns.maintainers',
4747
keywords: 'filters.columns.keywords',
4848
qualityScore: 'filters.columns.quality_score',

app/components/Package/Card.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ const pkgDescription = useMarkdown(() => ({
9494
<dd class="font-mono">{{ result.package.publisher.username }}</dd>
9595
</div>
9696
<div v-if="result.package.date" class="flex items-center gap-1.5">
97-
<dt class="sr-only">{{ $t('package.card.updated') }}</dt>
97+
<dt class="sr-only">{{ $t('package.card.published') }}</dt>
9898
<dd>
9999
<DateTime
100100
:datetime="result.package.date"

app/components/Package/ListControls.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const sortOptions = computed(
3333
() =>
3434
[
3535
{ value: 'downloads', label: $t('package.sort.downloads') },
36-
{ value: 'updated', label: $t('package.sort.updated') },
36+
{ value: 'updated', label: $t('package.sort.published') },
3737
{ value: 'name-asc', label: $t('package.sort.name_asc') },
3838
{ value: 'name-desc', label: $t('package.sort.name_desc') },
3939
] as const,

app/components/Package/ListToolbar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ const sortKeyLabelKeys: Record<SortKey, string> = {
9191
'downloads-day': 'filters.sort.downloads_day',
9292
'downloads-month': 'filters.sort.downloads_month',
9393
'downloads-year': 'filters.sort.downloads_year',
94-
'updated': 'filters.sort.updated',
94+
'updated': 'filters.sort.published',
9595
'name': 'filters.sort.name',
9696
'quality': 'filters.sort.quality',
9797
'popularity': 'filters.sort.popularity',

app/components/Package/Skeleton.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@
7070
</dd>
7171
</div>
7272

73-
<!-- Updated -->
73+
<!-- Published -->
7474
<div class="space-y-1 col-span-2">
7575
<dt class="text-xs text-fg-subtle uppercase tracking-wider">
76-
{{ $t('package.skeleton.updated') }}
76+
{{ $t('package.skeleton.published') }}
7777
</dt>
7878
<dd class="font-mono text-sm">
7979
<span class="skeleton inline-block h-5 w-28" />

app/components/Package/Table.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ const columnLabelKeys: Record<ColumnId, string> = {
8585
version: 'filters.columns.version',
8686
description: 'filters.columns.description',
8787
downloads: 'filters.columns.downloads',
88-
updated: 'filters.columns.updated',
88+
updated: 'filters.columns.published',
8989
maintainers: 'filters.columns.maintainers',
9090
keywords: 'filters.columns.keywords',
9191
qualityScore: 'filters.columns.quality_score',

app/components/Readme.vue

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,66 @@ defineProps<{
33
html: string
44
}>()
55
6+
const router = useRouter()
67
const { copy } = useClipboard()
78
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
1014
if (!target) return
1115
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
1421
15-
const pre = wrapper.querySelector('pre')
16-
if (!pre?.textContent) return
22+
const pre = wrapper.querySelector('pre')
23+
if (!pre?.textContent) return
1724
18-
await copy(pre.textContent)
25+
copy(pre.textContent)
1926
20-
const icon = target.querySelector('span')
21-
if (!icon) return
27+
const icon = copyTarget.querySelector('span')
28+
if (!icon) return
2229
23-
const originalIcon = 'i-carbon:copy'
24-
const successIcon = 'i-carbon:checkmark'
30+
const originalIcon = 'i-carbon:copy'
31+
const successIcon = 'i-carbon:checkmark'
2532
26-
icon.classList.remove(originalIcon)
27-
icon.classList.add(successIcon)
33+
icon.classList.remove(originalIcon)
34+
icon.classList.add(successIcon)
2835
29-
setTimeout(() => {
30-
icon.classList.remove(successIcon)
31-
icon.classList.add(originalIcon)
32-
}, 2000)
36+
setTimeout(() => {
37+
icon.classList.remove(successIcon)
38+
icon.classList.add(originalIcon)
39+
}, 2000)
40+
return
41+
}
42+
43+
// Handle npmjs.com link clicks - route internally
44+
const anchor = target.closest('a')
45+
if (!anchor) return
46+
47+
const href = anchor.getAttribute('href')
48+
if (!href) return
49+
50+
const match = href.match(/^(?:https?:\/\/)?(?:www\.)?npmjs\.(?:com|org)(\/.+)$/)
51+
if (!match || !match[1]) return
52+
53+
const route = router.resolve(match[1])
54+
if (route) {
55+
event.preventDefault()
56+
router.push(route)
57+
}
3358
}
3459
</script>
3560

3661
<template>
3762
<article
3863
class="readme prose prose-invert max-w-[70ch] lg:max-w-none px-1"
3964
v-html="html"
40-
@click="handleCopy"
65+
@click="handleClick"
4166
/>
4267
</template>
4368

app/composables/usePackageComparison.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ export interface PackageComparisonData {
2121
}
2222
metadata?: {
2323
license?: string
24+
/**
25+
* Publish date of this version (ISO 8601 date-time string).
26+
* Uses `time[version]` from the registry, NOT `time.modified`.
27+
* For example, if the package was most recently published 3 years ago
28+
* but a maintainer was removed last week, this would show the '3 years ago' time.
29+
*/
2430
lastUpdated?: string
2531
engines?: { node?: string; npm?: string }
2632
deprecated?: string
@@ -133,7 +139,9 @@ export function usePackageComparison(packageNames: MaybeRefOrGetter<string[]>) {
133139
},
134140
metadata: {
135141
license: pkgData.license,
136-
lastUpdated: pkgData.time?.modified,
142+
// Use version-specific publish time, NOT time.modified (which can be
143+
// updated by metadata changes like maintainer additions)
144+
lastUpdated: pkgData.time?.[latestVersion],
137145
engines: analysis?.engines,
138146
deprecated: versionData?.deprecated,
139147
},

app/pages/package/[...package].vue

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -385,24 +385,6 @@ defineOgImageComponent('Package', {
385385
stars: () => stars.value ?? 0,
386386
primaryColor: '#60a5fa',
387387
})
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-
}
406388
</script>
407389

408390
<template>
@@ -859,12 +841,23 @@ function handleClick(event: MouseEvent) {
859841
</template>
860842
</ClientOnly>
861843

862-
<div v-if="pkg.time?.modified" class="space-y-1 sm:col-span-2">
863-
<dt class="text-xs text-fg-subtle uppercase tracking-wider">
864-
{{ $t('package.stats.updated') }}
844+
<div
845+
v-if="resolvedVersion && pkg.time?.[resolvedVersion]"
846+
class="space-y-1 sm:col-span-2"
847+
>
848+
<dt
849+
class="text-xs text-fg-subtle uppercase tracking-wider"
850+
:title="
851+
$t('package.stats.published_tooltip', {
852+
package: pkg.name,
853+
version: resolvedVersion,
854+
})
855+
"
856+
>
857+
{{ $t('package.stats.published') }}
865858
</dt>
866859
<dd class="font-mono text-sm text-fg">
867-
<DateTime :datetime="pkg.time.modified" date-style="medium" />
860+
<DateTime :datetime="pkg.time[resolvedVersion]!" date-style="medium" />
868861
</dd>
869862
</div>
870863
</dl>
@@ -874,7 +867,7 @@ function handleClick(event: MouseEvent) {
874867
<PackageSkillsModal
875868
:skills="skillsData?.skills ?? []"
876869
:package-name="pkg.name"
877-
:version="displayVersion?.version"
870+
:version="resolvedVersion || undefined"
878871
/>
879872
</ClientOnly>
880873
</section>
@@ -972,7 +965,7 @@ function handleClick(event: MouseEvent) {
972965
</a>
973966
</h2>
974967
<!-- eslint-disable vue/no-v-html -- HTML is sanitized server-side -->
975-
<Readme v-if="readmeData?.html" :html="readmeData.html" @click="handleClick" />
968+
<Readme v-if="readmeData?.html" :html="readmeData.html" />
976969
<p v-else class="text-fg-subtle italic">
977970
{{ $t('package.readme.no_readme') }}
978971
<a
@@ -1029,7 +1022,7 @@ function handleClick(event: MouseEvent) {
10291022
v-if="skillsData?.skills?.length"
10301023
:skills="skillsData.skills"
10311024
:package-name="pkg.name"
1032-
:version="displayVersion?.version"
1025+
:version="resolvedVersion || undefined"
10331026
/>
10341027
</ClientOnly>
10351028

i18n/locales/ar.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@
142142
"deps": "الاعتماديات",
143143
"install_size": "حجم التثبيت",
144144
"vulns": "الثغرات",
145-
"updated": "آخر تحديث",
146145
"skills": "المهارات",
147146
"view_dependency_graph": "عرض مخطط الاعتماديات",
148147
"inspect_dependency_tree": "فحص شجرة الاعتماديات",
@@ -206,7 +205,6 @@
206205
"compatibility": "التوافق",
207206
"card": {
208207
"publisher": "الناشر",
209-
"updated": "آخر تحديث",
210208
"weekly_downloads": "التنزيلات الأسبوعية",
211209
"keywords": "الكلمات المفتاحية",
212210
"license": "الترخيص"
@@ -366,7 +364,6 @@
366364
"weekly": "أسبوعيًا",
367365
"size": "الحجم",
368366
"deps": "الاعتماديات",
369-
"updated": "آخر تحديث",
370367
"get_started": "ابدأ",
371368
"readme": "README",
372369
"maintainers": "المشرفون",
@@ -376,7 +373,6 @@
376373
},
377374
"sort": {
378375
"downloads": "الأكثر تنزيلًا",
379-
"updated": "مُحدَّثة مؤخرًا",
380376
"name_asc": "الاسم (A-Z)",
381377
"name_desc": "الاسم (Z-A)"
382378
}
@@ -661,7 +657,6 @@
661657
"downloads_day": "التنزيلات/اليوم",
662658
"downloads_month": "التنزيلات/الشهر",
663659
"downloads_year": "التنزيلات/السنة",
664-
"updated": "آخر تحديث",
665660
"name": "الاسم",
666661
"quality": "الجودة",
667662
"popularity": "الشعبية",
@@ -677,7 +672,6 @@
677672
"version": "الإصدار",
678673
"description": "الوصف",
679674
"downloads": "التنزيلات/الأسبوع",
680-
"updated": "آخر تحديث",
681675
"maintainers": "المشرفون",
682676
"keywords": "الكلمات المفتاحية",
683677
"quality_score": "درجة الجودة",

0 commit comments

Comments
 (0)