Skip to content

Commit 1d2d1ba

Browse files
committed
refactor: streamline link props and change how external links are recognized
1 parent 3654cd4 commit 1d2d1ba

9 files changed

Lines changed: 45 additions & 43 deletions

File tree

app/app.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ if (import.meta.client) {
121121
<template>
122122
<div class="min-h-screen flex flex-col bg-bg text-fg">
123123
<NuxtPwaAssets />
124-
<LinkBase href="#main-content" variant="button-primary" class="skip-link">{{
124+
<LinkBase to="#main-content" variant="button-primary" class="skip-link">{{
125125
$t('common.skip_link')
126126
}}</LinkBase>
127127

app/components/AppFooter.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ const isHome = computed(() => route.name === 'index')
1818
<LinkBase to="/about">
1919
{{ $t('footer.about') }}
2020
</LinkBase>
21-
<LinkBase href="https://docs.npmx.dev">
21+
<LinkBase to="https://docs.npmx.dev">
2222
{{ $t('footer.docs') }}
2323
</LinkBase>
24-
<LinkBase href="https://repo.npmx.dev">
24+
<LinkBase to="https://repo.npmx.dev">
2525
{{ $t('footer.source') }}
2626
</LinkBase>
27-
<LinkBase href="https://social.npmx.dev">
27+
<LinkBase to="https://social.npmx.dev">
2828
{{ $t('footer.social') }}
2929
</LinkBase>
30-
<LinkBase href="https://chat.npmx.dev">
30+
<LinkBase to="https://chat.npmx.dev">
3131
{{ $t('footer.chat') }}
3232
</LinkBase>
3333
</div>

app/components/BuildEnvironment.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ const buildInfo = useAppConfig().buildInfo
1919
<span>&middot;</span>
2020
<LinkBase
2121
v-if="buildInfo.env === 'release'"
22-
:href="`https://github.com/npmx-dev/npmx.dev/tag/v${buildInfo.version}`"
22+
:to="`https://github.com/npmx-dev/npmx.dev/tag/v${buildInfo.version}`"
2323
>
2424
v{{ buildInfo.version }}
2525
</LinkBase>
2626
<span v-else class="tracking-wider">{{ buildInfo.env }}</span>
2727

2828
<template v-if="buildInfo.commit && buildInfo.branch !== 'release'">
2929
<span>&middot;</span>
30-
<LinkBase :href="`https://github.com/npmx-dev/npmx.dev/commit/${buildInfo.commit}`">
30+
<LinkBase :to="`https://github.com/npmx-dev/npmx.dev/commit/${buildInfo.commit}`">
3131
{{ buildInfo.shortCommit }}
3232
</LinkBase>
3333
</template>

app/components/Link/Base.vue

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,22 @@ const props = withDefaults(
3232
'classicon'?: string
3333
3434
'to'?: NuxtLinkProps['to']
35-
'href'?: NuxtLinkProps['href']
35+
36+
/** always use `to` instead of `href` */
37+
'href'?: never
3638
} & NuxtLinkProps
3739
>(),
3840
{ variant: 'link' },
3941
)
4042
4143
const isLinkExternal = computed(
4244
() =>
43-
!!props.href &&
44-
typeof props.href === 'string' &&
45-
!props.href.startsWith('/') &&
46-
!props.href.startsWith('#'),
45+
!!props.to &&
46+
typeof props.to === 'string' &&
47+
(props.to.startsWith('http:') || props.to.startsWith('https:') || props.to.startsWith('//')),
4748
)
4849
const isLinkAnchor = computed(
49-
() => !!props.href && typeof props.href === 'string' && props.href.startsWith('#'),
50+
() => !!props.to && typeof props.to === 'string' && props.to.startsWith('#'),
5051
)
5152
</script>
5253

@@ -82,7 +83,8 @@ const isLinkAnchor = computed(
8283
variant === 'button-primary',
8384
}"
8485
:to="to"
85-
:href="href"
86+
:href="to"
87+
:external="isLinkExternal"
8688
:aria-keyshortcuts="keyshortcut"
8789
:target="isLinkExternal ? '_blank' : undefined"
8890
:rel="isLinkExternal ? 'noopener noreferrer' : undefined"

app/components/Package/Versions.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ function getTagVersions(tag: string): VersionDisplay[] {
309309
<template #actions>
310310
<LinkBase
311311
variant="button-secondary"
312-
:href="`https://majors.nullvoxpopuli.com/q?packages=${packageName}`"
312+
:to="`https://majors.nullvoxpopuli.com/q?packages=${packageName}`"
313313
:title="$t('package.downloads.community_distribution')"
314314
classicon="i-carbon:load-balancer-network"
315315
>

app/pages/about.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const { data: contributors, status: contributorsStatus } = useFetch<GitHubContri
7474
<strong class="text-fg">{{ $t('about.what_we_are.better_ux_dx') }}</strong>
7575
</template>
7676
<template #jsr>
77-
<LinkBase href="https://jsr.io/">JSR</LinkBase>
77+
<LinkBase to="https://jsr.io/">JSR</LinkBase>
7878
</template>
7979
</i18n-t>
8080
</p>
@@ -106,32 +106,32 @@ const { data: contributors, status: contributorsStatus } = useFetch<GitHubContri
106106
>
107107
<template #already>{{ $t('about.what_we_are_not.words.already') }}</template>
108108
<template #people>
109-
<LinkBase :href="pmLinks.npm">{{
109+
<LinkBase :to="pmLinks.npm">{{
110110
$t('about.what_we_are_not.words.people')
111111
}}</LinkBase>
112112
</template>
113113
<template #building>
114-
<LinkBase :href="pmLinks.pnpm">{{
114+
<LinkBase :to="pmLinks.pnpm">{{
115115
$t('about.what_we_are_not.words.building')
116116
}}</LinkBase>
117117
</template>
118118
<template #really>
119-
<LinkBase :href="pmLinks.yarn">{{
119+
<LinkBase :to="pmLinks.yarn">{{
120120
$t('about.what_we_are_not.words.really')
121121
}}</LinkBase>
122122
</template>
123123
<template #cool>
124-
<LinkBase :href="pmLinks.bun">{{
124+
<LinkBase :to="pmLinks.bun">{{
125125
$t('about.what_we_are_not.words.cool')
126126
}}</LinkBase>
127127
</template>
128128
<template #package>
129-
<LinkBase :href="pmLinks.deno">{{
129+
<LinkBase :to="pmLinks.deno">{{
130130
$t('about.what_we_are_not.words.package')
131131
}}</LinkBase>
132132
</template>
133133
<template #managers>
134-
<LinkBase :href="pmLinks.vlt">{{
134+
<LinkBase :to="pmLinks.vlt">{{
135135
$t('about.what_we_are_not.words.managers')
136136
}}</LinkBase>
137137
</template>

app/pages/package-code/[...path].vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ defineOgImageComponent('Default', {
492492
</p>
493493
<LinkBase
494494
variant="button-secondary"
495-
:href="`https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`"
495+
:to="`https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`"
496496
class="inline-flex items-center gap-2"
497497
>
498498
{{ $t('code.view_raw') }}
@@ -544,7 +544,7 @@ defineOgImageComponent('Default', {
544544
<p class="text-fg-subtle text-sm mb-4">{{ $t('code.unavailable_hint') }}</p>
545545
<LinkBase
546546
variant="button-secondary"
547-
:href="`https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`"
547+
:to="`https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}`"
548548
class="inline-flex items-center gap-2"
549549
>
550550
{{ $t('code.view_raw') }}

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ onKeyStroke(
574574
>
575575
<LinkBase
576576
variant="tag"
577-
href="#provenance"
577+
to="#provenance"
578578
:aria-label="$t('package.provenance_section.view_more_details')"
579579
classicon="i-lucide-shield-check"
580580
/>
@@ -696,7 +696,7 @@ onKeyStroke(
696696
<li v-if="repositoryUrl">
697697
<LinkBase
698698
variant="button-secondary"
699-
:href="repositoryUrl"
699+
:to="repositoryUrl"
700700
:classicon="repoProviderIcon"
701701
>
702702
<span v-if="repoRef">
@@ -706,24 +706,24 @@ onKeyStroke(
706706
</LinkBase>
707707
</li>
708708
<li v-if="repositoryUrl && repoMeta && starsLink">
709-
<LinkBase variant="button-secondary" :href="starsLink" classicon="i-carbon:star">
709+
<LinkBase variant="button-secondary" :to="starsLink" classicon="i-carbon:star">
710710
{{ formatCompactNumber(stars, { decimals: 1 }) }}
711711
</LinkBase>
712712
</li>
713713
<li v-if="forks && forksLink">
714-
<LinkBase variant="button-secondary" :href="forksLink" classicon="i-carbon:fork">
714+
<LinkBase variant="button-secondary" :to="forksLink" classicon="i-carbon:fork">
715715
{{ formatCompactNumber(forks, { decimals: 1 }) }}
716716
</LinkBase>
717717
</li>
718718
<li v-if="homepageUrl">
719-
<LinkBase variant="button-secondary" :href="homepageUrl" classicon="i-carbon:link">
719+
<LinkBase variant="button-secondary" :to="homepageUrl" classicon="i-carbon:link">
720720
{{ $t('package.links.homepage') }}
721721
</LinkBase>
722722
</li>
723723
<li v-if="displayVersion?.bugs?.url">
724724
<LinkBase
725725
variant="button-secondary"
726-
:href="displayVersion.bugs.url"
726+
:to="displayVersion.bugs.url"
727727
classicon="i-carbon:warning"
728728
>
729729
{{ $t('package.links.issues') }}
@@ -732,7 +732,7 @@ onKeyStroke(
732732
<li>
733733
<LinkBase
734734
variant="button-secondary"
735-
:href="`https://www.npmjs.com/package/${pkg.name}`"
735+
:to="`https://www.npmjs.com/package/${pkg.name}`"
736736
:title="$t('common.view_on_npm')"
737737
classicon="i-carbon:logo-npm"
738738
>
@@ -742,15 +742,15 @@ onKeyStroke(
742742
<li v-if="jsrInfo?.exists && jsrInfo.url">
743743
<LinkBase
744744
variant="button-secondary"
745-
:href="jsrInfo.url"
745+
:to="jsrInfo.url"
746746
:title="$t('badges.jsr.title')"
747747
classicon="i-simple-icons:jsr"
748748
>
749749
{{ $t('package.links.jsr') }}
750750
</LinkBase>
751751
</li>
752752
<li v-if="fundingUrl">
753-
<LinkBase variant="button-secondary" :href="fundingUrl" classicon="i-carbon:favorite">
753+
<LinkBase variant="button-secondary" :to="fundingUrl" classicon="i-carbon:favorite">
754754
{{ $t('package.links.fund') }}
755755
</LinkBase>
756756
</li>
@@ -853,7 +853,7 @@ onKeyStroke(
853853
<LinkBase
854854
variant="tag"
855855
v-if="getDependencyCount(displayVersion) > 0"
856-
:href="`https://npmgraph.js.org/?q=${pkg.name}`"
856+
:to="`https://npmgraph.js.org/?q=${pkg.name}`"
857857
:title="$t('package.stats.view_dependency_graph')"
858858
classicon="i-carbon:network-3"
859859
>
@@ -863,7 +863,7 @@ onKeyStroke(
863863
<LinkBase
864864
variant="tag"
865865
v-if="getDependencyCount(displayVersion) > 0"
866-
:href="`https://node-modules.dev/grid/depth#install=${pkg.name}${resolvedVersion ? `@${resolvedVersion}` : ''}`"
866+
:to="`https://node-modules.dev/grid/depth#install=${pkg.name}${resolvedVersion ? `@${resolvedVersion}` : ''}`"
867867
:title="$t('package.stats.inspect_dependency_tree')"
868868
classicon="i-carbon:tree-view"
869869
>
@@ -1011,7 +1011,7 @@ onKeyStroke(
10111011
id="get-started-heading"
10121012
class="group text-xs text-fg-subtle uppercase tracking-wider"
10131013
>
1014-
<LinkBase href="#get-started">
1014+
<LinkBase to="#get-started">
10151015
{{ $t('package.get_started.title') }}
10161016
</LinkBase>
10171017
</h2>
@@ -1057,7 +1057,7 @@ onKeyStroke(
10571057
<section id="readme" class="area-readme min-w-0 scroll-mt-20">
10581058
<div class="flex flex-wrap items-center justify-between mb-3 px-1">
10591059
<h2 id="readme-heading" class="group text-xs text-fg-subtle uppercase tracking-wider">
1060-
<LinkBase href="#readme">
1060+
<LinkBase to="#readme">
10611061
{{ $t('package.readme.title') }}
10621062
</LinkBase>
10631063
</h2>

test/nuxt/a11y.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ describe('component accessibility audits', () => {
330330
describe('LinkBase', () => {
331331
it('should have no accessibility violations', async () => {
332332
const component = await mountSuspended(LinkBase, {
333-
props: { href: 'http://example.com' },
333+
props: { to: 'http://example.com' },
334334
slots: { default: 'Button link content' },
335335
})
336336
const results = await runAxe(component)
@@ -339,7 +339,7 @@ describe('component accessibility audits', () => {
339339

340340
it("should have no accessibility violations when it's the current link", async () => {
341341
const component = await mountSuspended(LinkBase, {
342-
props: { href: 'http://example.com', current: true },
342+
props: { to: 'http://example.com', current: true },
343343
slots: { default: 'Button link content' },
344344
})
345345
const results = await runAxe(component)
@@ -348,7 +348,7 @@ describe('component accessibility audits', () => {
348348

349349
it('should have no accessibility violations when disabled (plain text)', async () => {
350350
const component = await mountSuspended(LinkBase, {
351-
props: { href: 'http://example.com', disabled: true },
351+
props: { to: 'http://example.com', disabled: true },
352352
slots: { default: 'Button link content' },
353353
})
354354
const results = await runAxe(component)
@@ -357,7 +357,7 @@ describe('component accessibility audits', () => {
357357

358358
it('should have no accessibility violations as secondary button', async () => {
359359
const component = await mountSuspended(LinkBase, {
360-
props: { href: 'http://example.com', disabled: true, variant: 'button-secondary' },
360+
props: { to: 'http://example.com', disabled: true, variant: 'button-secondary' },
361361
slots: { default: 'Button link content' },
362362
})
363363
const results = await runAxe(component)
@@ -366,7 +366,7 @@ describe('component accessibility audits', () => {
366366

367367
it('should have no accessibility violations as primary button', async () => {
368368
const component = await mountSuspended(LinkBase, {
369-
props: { href: 'http://example.com', disabled: true, variant: 'button-primary' },
369+
props: { to: 'http://example.com', disabled: true, variant: 'button-primary' },
370370
slots: { default: 'Button link content' },
371371
})
372372
const results = await runAxe(component)
@@ -375,7 +375,7 @@ describe('component accessibility audits', () => {
375375

376376
it('should have no accessibility violations as tag', async () => {
377377
const component = await mountSuspended(LinkBase, {
378-
props: { href: 'http://example.com', disabled: true, variant: 'tag' },
378+
props: { to: 'http://example.com', disabled: true, variant: 'tag' },
379379
slots: { default: 'Button link content' },
380380
})
381381
const results = await runAxe(component)

0 commit comments

Comments
 (0)