Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c062ad6
feat(docs): add custom badge generator
Mar 19, 2026
89d5ebf
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
9e467d0
fix: add name type
trueberryless Mar 19, 2026
3907e95
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
8101797
feat: create parameter badge generator
trueberryless Mar 19, 2026
381114c
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
a1821ff
feat: add label formatter and make clipboard robust
trueberryless Mar 19, 2026
ffa83af
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless Mar 19, 2026
2d41b40
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 19, 2026
3eff748
refactor: simplify clipboard
trueberryless Mar 20, 2026
18b79c2
fix: suggestions
trueberryless Mar 20, 2026
124dada
feat: support any value
trueberryless Mar 20, 2026
39be64f
Merge branch 'main' into feature/docs-custom-badges-inputs
trueberryless Mar 20, 2026
761b683
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 20, 2026
263bb3f
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv Mar 21, 2026
706b3ac
refactor: badge types constant should be shared
ghostdevv Mar 21, 2026
cdd74d3
refactor: use text transform to capitalise
ghostdevv Mar 21, 2026
2b2deec
fix: knip
ghostdevv Mar 21, 2026
0d98502
Revert "refactor: use text transform to capitalise"
ghostdevv Mar 21, 2026
fba0dc5
refactor: typescript
ghostdevv Mar 21, 2026
850618a
refactor: reusable titleCase fn
ghostdevv Mar 21, 2026
a588ac1
Merge remote-tracking branch 'origin/main' into feature/docs-custom-b…
ghostdevv Mar 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions docs/app/components/BadgeGenerator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<script setup>
const pkg = useState('badge-pkg', () => 'nuxt')
const type = useState('badge-type', () => 'version')
const isValid = ref(true)
const copied = ref(false)

const types = [
'version',
'license',
'size',
'downloads',
'downloads-day',
'downloads-week',
'downloads-month',
'downloads-year',
'vulnerabilities',
'dependencies',
'created',
'updated',
'engines',
'types',
'maintainers',
'deprecated',
'quality',
'popularity',
'maintenance',
'score',
'name',
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

watch(pkg, () => {
isValid.value = true
})
Comment thread
trueberryless marked this conversation as resolved.
Outdated

const formatLabel = str => {
if (!str || typeof str !== 'string') return ''
return str
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' per ')
}

const copyToClipboard = async () => {
const markdown = `[![Open on npmx.dev](https://npmx.dev/api/registry/badge/${type.value}/${pkg.value})](https://npmx.dev/package/${pkg.value})`
try {
await navigator.clipboard.writeText(markdown)
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
} catch {
console.error('Failed to copy to clipboard')

Check warning on line 52 in docs/app/components/BadgeGenerator.vue

View workflow job for this annotation

GitHub Actions / 🤖 Autofix code

eslint(no-console)

Unexpected console statement.
Comment thread
trueberryless marked this conversation as resolved.
Outdated
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</script>

<template>
<div
class="my-8 p-5 rounded-xl border border-gray-200/60 dark:border-white/5 bg-gray-50/50 dark:bg-white/2 flex flex-col sm:flex-row items-end gap-4"
>
<div class="flex flex-col gap-1.5 flex-1 w-full">
<label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1"
>Package Name</label
>
<input
v-model="pkg"
type="text"
spellcheck="false"
class="w-full h-10.5 px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all"
:class="{ 'border-red-500/50 focus:ring-red-500/10 focus:border-red-500': !isValid }"
placeholder="e.g. nuxt"
/>
</div>

<div class="flex flex-col gap-1.5 flex-1 w-full">
<label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1"
>Badge Type</label
>
<div class="relative">
<select
v-model="type"
class="w-full h-10.5 px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all appearance-none cursor-pointer"
>
<option v-for="t in types" :key="t" :value="t" class="dark:bg-gray-900">
{{ formatLabel(t) }}
</option>
</select>
<span
class="absolute right-3 top-1/2 -translate-y-1/2 i-lucide-chevron-down w-4 h-4 text-gray-400 pointer-events-none"
/>
</div>
</div>

<div class="flex flex-col gap-1.5 flex-2 w-full">
<label class="text-[11px] font-bold uppercase tracking-wider text-gray-400 ml-1"
>Preview & Action</label
>
<div
class="flex items-center bg-white dark:bg-black/20 border border-gray-200 dark:border-white/10 rounded-lg h-10.5 overflow-hidden"
>
<div
class="flex-1 flex items-center justify-center px-3 border-r border-gray-200 dark:border-white/10 h-full bg-gray-50/50 dark:bg-transparent"
>
<img
v-if="isValid"
:src="`https://npmx.dev/api/registry/badge/${type}/${pkg}`"
class="h-5"
alt="Badge Preview"
@error="isValid = false"
/>
<span v-else class="text-[10px] font-bold text-red-500 uppercase tracking-tighter"
>Invalid</span
>
</div>

<button
@click="copyToClipboard"
:disabled="!isValid"
Comment thread
trueberryless marked this conversation as resolved.
Outdated
class="px-4 h-full text-[11px] font-bold uppercase tracking-widest transition-all disabled:opacity-20 disabled:cursor-not-allowed min-w-21.25 hover:bg-gray-50 dark:hover:bg-white/5"
:class="
copied
? 'text-emerald-500 bg-emerald-50/50 dark:bg-emerald-500/10'
: 'text-gray-500 dark:text-gray-400'
"
>
{{ copied ? 'Done!' : 'Copy' }}
</button>
</div>
</div>
</div>
</template>
Loading
Loading