Skip to content

Commit 2ca089f

Browse files
Merge branch 'main' into feat/add-pm-dropdown
2 parents 2e663a0 + 7cf66b2 commit 2ca089f

File tree

11 files changed

+153
-86
lines changed

11 files changed

+153
-86
lines changed

app/components/PackageDownloadAnalytics.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ const config = computed(() => {
463463
return {
464464
theme: isDarkMode.value ? 'dark' : 'default',
465465
chart: {
466-
height: isMobile.value ? 850 : 600,
466+
height: isMobile.value ? 950 : 600,
467467
userOptions: {
468468
buttons: {
469469
pdf: false,
@@ -508,15 +508,17 @@ const config = computed(() => {
508508
grid: {
509509
stroke: colors.value.border,
510510
labels: {
511+
fontSize: isMobile.value ? 24 : 16,
511512
axis: {
512513
yLabel: $t('package.downloads.y_axis_label', {
513514
granularity: $t(`package.downloads.granularity_${selectedGranularity.value}`),
514515
}),
515516
xLabel: packageName,
516517
yLabelOffsetX: 12,
517-
fontSize: 24,
518+
fontSize: isMobile.value ? 32 : 24,
518519
},
519520
xAxisLabels: {
521+
show: !isMobile.value,
520522
values: chartData.value?.dates,
521523
showOnlyAtModulo: true,
522524
modulo: 12,
@@ -554,7 +556,7 @@ const config = computed(() => {
554556
},
555557
},
556558
zoom: {
557-
maxWidth: 500,
559+
maxWidth: isMobile.value ? 350 : 500,
558560
customFormat:
559561
displayedGranularity.value !== 'weekly'
560562
? undefined

app/components/PackageReplacement.vue

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@ const props = defineProps<{
55
replacement: ModuleReplacement
66
}>()
77
8-
const { t } = useI18n()
9-
10-
const message = computed(() => {
8+
const message = computed<[string, { replacement?: string; nodeVersion?: string }]>(() => {
119
switch (props.replacement.type) {
1210
case 'native':
13-
return t('package.replacement.native', {
14-
replacement: props.replacement.replacement,
15-
nodeVersion: props.replacement.nodeVersion,
16-
})
11+
return [
12+
'package.replacement.native',
13+
{
14+
replacement: props.replacement.replacement,
15+
nodeVersion: props.replacement.nodeVersion,
16+
},
17+
]
1718
case 'simple':
18-
return t('package.replacement.simple', {
19-
replacement: props.replacement.replacement,
20-
})
19+
return [
20+
'package.replacement.simple',
21+
{
22+
replacement: props.replacement.replacement,
23+
},
24+
]
2125
case 'documented':
22-
return t('package.replacement.documented')
26+
return ['package.replacement.documented', {}]
2327
case 'none':
24-
return t('package.replacement.none')
28+
return ['package.replacement.none', {}]
2529
}
2630
})
2731
@@ -45,7 +49,25 @@ const docPath = computed(() => {
4549
{{ $t('package.replacement.title') }}
4650
</h2>
4751
<p class="text-sm m-0">
48-
{{ message }}
52+
<i18n-t :keypath="message[0]" scope="global">
53+
<template #replacement>
54+
{{ message[1].replacement ?? '' }}
55+
</template>
56+
<template #nodeVersion>
57+
{{ message[1].nodeVersion ?? '' }}
58+
</template>
59+
<template #community>
60+
<a
61+
href="https://e18e.dev/docs/replacements/"
62+
target="_blank"
63+
rel="noopener noreferrer"
64+
class="inline-flex items-center gap-1 ms-1 underline underline-offset-4 decoration-amber-600/60 dark:decoration-amber-400/50 hover:decoration-fg transition-colors"
65+
>
66+
{{ $t('package.replacement.community') }}
67+
<span class="i-carbon-launch w-3 h-3" aria-hidden="true" />
68+
</a>
69+
</template>
70+
</i18n-t>
4971
<a
5072
v-if="mdnUrl"
5173
:href="mdnUrl"

app/components/PackageVersions.vue

Lines changed: 65 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,14 @@ const visibleTagRows = computed(() => {
109109
const rows = isPackageDeprecated.value
110110
? allTagRows.value
111111
: allTagRows.value.filter(row => !row.primaryVersion.deprecated)
112-
return rows.slice(0, MAX_VISIBLE_TAGS)
112+
const first = rows.slice(0, MAX_VISIBLE_TAGS)
113+
const latestTagRow = rows.find(row => row.tag === 'latest')
114+
// Ensure 'latest' tag is always included (at the end) if not already present
115+
if (latestTagRow && !first.includes(latestTagRow)) {
116+
first.pop()
117+
first.push(latestTagRow)
118+
}
119+
return first
113120
})
114121
115122
// Hidden tag rows (all other tags) - shown in "Other versions"
@@ -322,7 +329,10 @@ function getTagVersions(tag: string): VersionDisplay[] {
322329
<div class="space-y-0.5 min-w-0">
323330
<!-- Dist-tag rows (limited to MAX_VISIBLE_TAGS) -->
324331
<div v-for="row in visibleTagRows" :key="row.id">
325-
<div class="flex items-center gap-2">
332+
<div
333+
class="flex items-center gap-2 pe-2"
334+
:class="row.tag === 'latest' ? 'bg-bg-subtle rounded-lg' : ''"
335+
>
326336
<!-- Expand button (only if there are more versions to show) -->
327337
<button
328338
v-if="getTagVersions(row.tag).length > 1 || !hasLoadedAll"
@@ -354,65 +364,67 @@ function getTagVersions(tag: string): VersionDisplay[] {
354364
<span v-else class="w-4" />
355365

356366
<!-- Version info -->
357-
<div class="flex-1 py-1.5 min-w-0">
358-
<div class="flex items-center justify-between gap-2">
359-
<NuxtLink
360-
:to="versionRoute(row.primaryVersion.version)"
361-
class="font-mono text-sm transition-colors duration-200 truncate inline-flex items-center gap-1"
362-
:class="
363-
row.primaryVersion.deprecated
364-
? 'text-red-400 hover:text-red-300'
365-
: 'text-fg-muted hover:text-fg'
366-
"
367-
:title="
368-
row.primaryVersion.deprecated
369-
? $t('package.versions.deprecated_title', {
370-
version: row.primaryVersion.version,
371-
})
372-
: row.primaryVersion.version
373-
"
374-
>
367+
<div class="flex-1 py-1.5 min-w-0 flex gap-2 justify-between items-center">
368+
<div>
369+
<div>
370+
<NuxtLink
371+
:to="versionRoute(row.primaryVersion.version)"
372+
class="font-mono text-sm transition-colors duration-200 truncate inline-flex items-center gap-1"
373+
:class="
374+
row.primaryVersion.deprecated
375+
? 'text-red-400 hover:text-red-300'
376+
: 'text-fg-muted hover:text-fg'
377+
"
378+
:title="
379+
row.primaryVersion.deprecated
380+
? $t('package.versions.deprecated_title', {
381+
version: row.primaryVersion.version,
382+
})
383+
: row.primaryVersion.version
384+
"
385+
>
386+
<span
387+
v-if="row.primaryVersion.deprecated"
388+
class="i-carbon-warning-hex w-3.5 h-3.5 shrink-0"
389+
aria-hidden="true"
390+
/>
391+
{{ row.primaryVersion.version }}
392+
</NuxtLink>
393+
</div>
394+
<div v-if="row.tags.length" class="flex items-center gap-1 mt-0.5 flex-wrap">
375395
<span
376-
v-if="row.primaryVersion.deprecated"
377-
class="i-carbon-warning-hex w-3.5 h-3.5 shrink-0"
378-
aria-hidden="true"
379-
/>
380-
{{ row.primaryVersion.version }}
381-
</NuxtLink>
382-
<div class="flex items-center gap-2 shrink-0">
383-
<DateTime
384-
v-if="row.primaryVersion.time"
385-
:datetime="row.primaryVersion.time"
386-
year="numeric"
387-
month="short"
388-
day="numeric"
389-
class="text-xs text-fg-subtle"
390-
/>
391-
<ProvenanceBadge
392-
v-if="row.primaryVersion.hasProvenance"
393-
:package-name="packageName"
394-
:version="row.primaryVersion.version"
395-
compact
396-
/>
396+
v-for="tag in row.tags"
397+
:key="tag"
398+
class="text-[9px] font-semibold text-fg-subtle uppercase tracking-wide truncate max-w-[150px]"
399+
:title="tag"
400+
>
401+
{{ tag }}
402+
</span>
397403
</div>
398404
</div>
399-
<div v-if="row.tags.length" class="flex items-center gap-1 mt-0.5 flex-wrap">
400-
<span
401-
v-for="tag in row.tags"
402-
:key="tag"
403-
class="text-[9px] font-semibold text-fg-subtle uppercase tracking-wide truncate max-w-[150px]"
404-
:title="tag"
405-
>
406-
{{ tag }}
407-
</span>
405+
<div class="flex items-center gap-2 shrink-0">
406+
<DateTime
407+
v-if="row.primaryVersion.time"
408+
:datetime="row.primaryVersion.time"
409+
year="numeric"
410+
month="short"
411+
day="numeric"
412+
class="text-xs text-fg-subtle"
413+
/>
414+
<ProvenanceBadge
415+
v-if="row.primaryVersion.hasProvenance"
416+
:package-name="packageName"
417+
:version="row.primaryVersion.version"
418+
compact
419+
/>
408420
</div>
409421
</div>
410422
</div>
411423

412424
<!-- Expanded versions -->
413425
<div
414426
v-if="expandedTags.has(row.tag) && getTagVersions(row.tag).length > 1"
415-
class="ms-4 ps-2 border-is border-border space-y-0.5"
427+
class="ms-4 ps-2 border-is border-border space-y-0.5 pe-2"
416428
>
417429
<div v-for="v in getTagVersions(row.tag).slice(1)" :key="v.version" class="py-1">
418430
<div class="flex items-center justify-between gap-2">
@@ -542,7 +554,7 @@ function getTagVersions(tag: string): VersionDisplay[] {
542554
/>
543555
{{ row.primaryVersion.version }}
544556
</NuxtLink>
545-
<div class="flex items-center gap-2 shrink-0">
557+
<div class="flex items-center gap-2 shrink-0 pe-2">
546558
<DateTime
547559
v-if="row.primaryVersion.time"
548560
:datetime="row.primaryVersion.time"
@@ -618,7 +630,7 @@ function getTagVersions(tag: string): VersionDisplay[] {
618630
{{ group.versions[0]?.version }}
619631
</NuxtLink>
620632
</div>
621-
<div class="flex items-center gap-2 shrink-0">
633+
<div class="flex items-center gap-2 shrink-0 pe-2">
622634
<DateTime
623635
v-if="group.versions[0]?.time"
624636
:datetime="group.versions[0]?.time"

app/pages/docs/[...path].vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,16 @@ const showEmptyState = computed(() => docsData.value?.status !== 'ok')
364364
@apply text-badge-orange text-sm;
365365
}
366366
367-
.docs-content .docs-deprecated p {
368-
@apply text-badge-orange text-sm mt-2 mb-0;
367+
.docs-content .docs-deprecated-message {
368+
@apply text-badge-orange text-sm mt-2;
369+
}
370+
371+
.docs-content .docs-deprecated-message code {
372+
@apply bg-badge-orange/20 text-badge-orange;
373+
}
374+
375+
.docs-content .docs-deprecated-message .docs-link {
376+
@apply text-badge-orange;
369377
}
370378
371379
/* Parameters, Returns, Examples, See Also sections */

i18n/locales/de-DE.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,12 @@
119119
"replacement": {
120120
"title": "Du brauchst diese Abhängigkeit vielleicht nicht.",
121121
"native": "Dies kann durch {replacement} ersetzt werden, verfügbar seit Node {nodeVersion}.",
122-
"simple": "Die Community hat dieses Paket als überflüssig markiert und empfiehlt: {replacement}.",
123-
"documented": "Die Community hat dieses Paket als eines mit leistungsstärkeren Alternativen markiert.",
122+
"simple": "Die {community} hat dieses Paket als überflüssig markiert und empfiehlt: {replacement}.",
123+
"documented": "Die {community} hat dieses Paket als eines mit leistungsstärkeren Alternativen markiert.",
124124
"none": "Dieses Paket wurde als nicht mehr nötig markiert, und seine Funktionen sind wahrscheinlich in allen Engines von Haus aus verfügbar.",
125125
"learn_more": "Mehr erfahren",
126-
"mdn": "MDN"
126+
"mdn": "MDN",
127+
"community": "Community"
127128
},
128129
"stats": {
129130
"license": "Lizenz",

i18n/locales/en.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,12 @@
119119
"replacement": {
120120
"title": "You might not need this dependency.",
121121
"native": "This can be replaced with {replacement}, available since Node {nodeVersion}.",
122-
"simple": "The community has flagged this package as redundant, with the advice: {replacement}.",
123-
"documented": "The community has flagged this package as having more performant alternatives.",
122+
"simple": "The {community} has flagged this package as redundant, with the advice: {replacement}.",
123+
"documented": "The {community} has flagged this package as having more performant alternatives.",
124124
"none": "This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.",
125125
"learn_more": "Learn more",
126-
"mdn": "MDN"
126+
"mdn": "MDN",
127+
"community": "community"
127128
},
128129
"stats": {
129130
"license": "License",

lunaria/files/de-DE.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,12 @@
119119
"replacement": {
120120
"title": "Du brauchst diese Abhängigkeit vielleicht nicht.",
121121
"native": "Dies kann durch {replacement} ersetzt werden, verfügbar seit Node {nodeVersion}.",
122-
"simple": "Die Community hat dieses Paket als überflüssig markiert und empfiehlt: {replacement}.",
123-
"documented": "Die Community hat dieses Paket als eines mit leistungsstärkeren Alternativen markiert.",
122+
"simple": "Die {community} hat dieses Paket als überflüssig markiert und empfiehlt: {replacement}.",
123+
"documented": "Die {community} hat dieses Paket als eines mit leistungsstärkeren Alternativen markiert.",
124124
"none": "Dieses Paket wurde als nicht mehr nötig markiert, und seine Funktionen sind wahrscheinlich in allen Engines von Haus aus verfügbar.",
125125
"learn_more": "Mehr erfahren",
126-
"mdn": "MDN"
126+
"mdn": "MDN",
127+
"community": "Community"
127128
},
128129
"stats": {
129130
"license": "Lizenz",

lunaria/files/en-US.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,12 @@
119119
"replacement": {
120120
"title": "You might not need this dependency.",
121121
"native": "This can be replaced with {replacement}, available since Node {nodeVersion}.",
122-
"simple": "The community has flagged this package as redundant, with the advice: {replacement}.",
123-
"documented": "The community has flagged this package as having more performant alternatives.",
122+
"simple": "The {community} has flagged this package as redundant, with the advice: {replacement}.",
123+
"documented": "The {community} has flagged this package as having more performant alternatives.",
124124
"none": "This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.",
125125
"learn_more": "Learn more",
126-
"mdn": "MDN"
126+
"mdn": "MDN",
127+
"community": "community"
127128
},
128129
"stats": {
129130
"license": "License",

server/utils/docs/render.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ async function renderJsDocTags(tags: JsDocTag[], symbolLookup: SymbolLookup): Pr
184184
lines.push(`<div class="docs-deprecated">`)
185185
lines.push(`<strong>Deprecated</strong>`)
186186
if (deprecated.doc) {
187-
lines.push(`<p>${parseJsDocLinks(deprecated.doc, symbolLookup)}</p>`)
187+
// We remove new lines because they look weird when rendered into the deprecated block
188+
// I think markdown is actually supposed to collapse single new lines automatically but this function doesn't do that so if that changes remove this
189+
const renderedMessage = await renderMarkdown(deprecated.doc.replace(/\n/g, ' '), symbolLookup)
190+
lines.push(`<div class="docs-deprecated-message">${renderedMessage}</div>`)
188191
}
189192
lines.push(`</div>`)
190193
}

server/utils/docs/text.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export function parseJsDocLinks(text: string, symbolLookup: SymbolLookup): strin
7575

7676
// External URL
7777
if (target.startsWith('http://') || target.startsWith('https://')) {
78-
return `<a href="${target}" target="_blank" rel="noopener" class="docs-link">${displayText}</a>`
78+
return `<a href="${target}" target="_blank" rel="noreferrer" class="docs-link">${displayText}</a>`
7979
}
8080

8181
// Internal symbol reference
@@ -116,6 +116,12 @@ export async function renderMarkdown(text: string, symbolLookup: SymbolLookup):
116116
// Now process the rest (JSDoc links, HTML escaping, etc.)
117117
result = parseJsDocLinks(result, symbolLookup)
118118

119+
// Markdown links - i.e. [text](url)
120+
result = result.replace(
121+
/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g,
122+
'<a href="$2" target="_blank" rel="noreferrer" class="docs-link">$1</a>',
123+
)
124+
119125
// Handle inline code (single backticks) - won't interfere with fenced blocks
120126
result = result
121127
.replace(/`([^`]+)`/g, '<code class="docs-inline-code">$1</code>')

0 commit comments

Comments
 (0)