Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: "\U0001F41E Bug report"
description: Create a report to help us improve npmx
type: bug
labels: ['pending triage']
body:
- type: markdown
attributes:
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature-request.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: '🚀 Feature request'
description: Suggest a feature that will improve npmx
type: feature
labels: ['pending triage']
body:
- type: markdown
Expand Down
65 changes: 65 additions & 0 deletions .storybook/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,68 @@ export const pdsUsersHandler = http.get('/api/atproto/pds-users', () => {
},
])
})

export const i18nStatusHandler = http.get('/lunaria/status.json', () => {
return HttpResponse.json({
generatedAt: '2026-01-22T10:07:07.000Z',
sourceLocale: {
lang: 'en',
label: 'English',
totalKeys: 500,
},
locales: [
{
lang: 'en-GB',
label: 'English (UK)',
dir: 'ltr',
totalKeys: 500,
completedKeys: 423,
percentComplete: 84,
missingKeys: [
'settings.background_themes.label',
'settings.enable_graph_pulse_loop',
'settings.enable_graph_pulse_loop_description',
'settings.data_source.algolia_description',
'settings.data_source.npm_description',
'i18n.contribute_hint',
'i18n.copy_keys',
],
githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/en-GB.json',
githubHistoryUrl:
'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/en-GB.json',
},
{
lang: 'fr-FR',
label: 'Français',
dir: 'ltr',
totalKeys: 500,
completedKeys: 423,
percentComplete: 84,
missingKeys: [
'settings.background_themes.label',
'settings.enable_graph_pulse_loop',
'settings.enable_graph_pulse_loop_description',
'settings.data_source.algolia_description',
'settings.data_source.npm_description',
'i18n.contribute_hint',
'i18n.copy_keys',
],
githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/fr-FR.json',
githubHistoryUrl:
'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/fr-FR.json',
},
{
lang: 'de-DE',
label: 'Deutsch',
dir: 'ltr',
totalKeys: 500,
completedKeys: 500,
percentComplete: 100,
missingKeys: [],
githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/de-DE.json',
githubHistoryUrl:
'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/de-DE.json',
},
],
})
})
16 changes: 16 additions & 0 deletions .storybook/preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,19 @@
background-color: var(--bg, oklch(0.171 0 0)) !important;
}
</style>
<script>
// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
// Stub Nuxt specific globals
// @nuxtjs/color-mode's plugin.client.js reads window[globalName] at module
// evaluation time — before any Storybook setup() callback runs — so the
// global must exist in the HTML head, not in preview.ts.
window.__NUXT_COLOR_MODE__ ??= {
preference: 'system',
value: 'dark',
getColorScheme: function () {
return 'dark'
},
addColorScheme: function () {},
removeColorScheme: function () {},
}
</script>
10 changes: 0 additions & 10 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@ import npmxDark from './theme'

initialize()

// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
// Stub Nuxt specific globals
// @ts-expect-error - dynamic global name
globalThis['__NUXT_COLOR_MODE__'] ??= {
preference: 'system',
value: 'dark',
getColorScheme: fn(() => 'dark'),
addColorScheme: fn(),
removeColorScheme: fn(),
}
// @ts-expect-error - dynamic global name
globalThis.defineOgImageComponent = fn()

Expand Down
4 changes: 4 additions & 0 deletions app/components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ const closeModal = () => modalRef.value?.close?.()
<kbd class="kbd">f</kbd>
<span>{{ $t('shortcuts.open_diff') }}</span>
</li>
<li class="flex gap-2 items-center">
<kbd class="kbd">t</kbd>
<span>{{ $t('shortcuts.open_timeline') }}</span>
</li>
<li class="flex gap-2 items-center">
<kbd class="kbd">c</kbd>
<span>{{ $t('shortcuts.compare_from_package') }}</span>
Expand Down
6 changes: 6 additions & 0 deletions app/components/Chart/SplitSparkline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const props = defineProps<{

const { locale } = useI18n()
const colorMode = useColorMode()
const numberFormatter = useNumberFormatter({
maximumFractionDigits: 0,
})
const resolvedMode = shallowRef<'light' | 'dark'>('light')
const rootEl = shallowRef<HTMLElement | null>(null)
const palette = getPalette('')
Expand Down Expand Up @@ -153,6 +156,9 @@ const configs = computed(() => {
fontSize: 24,
bold: false,
color: colors.value.fg,
formatter: ({ value }) => {
return numberFormatter.value.format(value)
},
datetimeFormatter: {
enable: true,
locale: locale.value,
Expand Down
25 changes: 24 additions & 1 deletion app/components/Package/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const props = defineProps<{
latestVersion?: SlimVersion | null
provenanceData?: ProvenanceDetails | null
provenanceStatus?: string | null
page: 'main' | 'docs' | 'code' | 'diff'
page: 'main' | 'docs' | 'code' | 'diff' | 'timeline'
versionUrlPattern: string
}>()

Expand Down Expand Up @@ -162,12 +162,26 @@ const diffLink = computed((): RouteLocationRaw | null => {
return diffRoute(props.pkg.name, props.resolvedVersion, props.latestVersion.version)
})

const timelineLink = computed((): RouteLocationRaw | null => {
if (props.pkg == null || props.resolvedVersion == null) return null
const split = props.pkg.name.split('/')
return {
name: 'timeline',
params: {
org: split.length === 2 ? split[0] : undefined,
packageName: split.length === 2 ? split[1]! : split[0]!,
version: props.resolvedVersion,
},
}
})

useShortcuts({
'.': () => codeLink.value,
'm': () => mainLink.value,
'd': () => docsLink.value,
'c': () => props.pkg && { name: 'compare' as const, query: { packages: props.pkg.name } },
'f': () => diffLink.value,
't': () => timelineLink.value,
})
</script>

Expand Down Expand Up @@ -330,6 +344,15 @@ useShortcuts({
>
{{ $t('compare.compare_versions') }}
</LinkBase>
<LinkBase
v-if="timelineLink"
:to="timelineLink"
aria-keyshortcuts="t"
class="decoration-none border-b-2 p-1 hover:border-accent/50 focus-visible:[outline-offset:-2px]!"
:class="page === 'timeline' ? 'border-accent text-accent!' : 'border-transparent'"
>
{{ $t('package.links.timeline') }}
</LinkBase>
</nav>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/Package/TrendsChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ const chartConfig = computed<VueUiXyConfig>(() => {
const rows = items
.map((d: Record<string, any>) => {
const label = String(d?.name ?? '').trim()
const raw = Number(d?.value ?? 0)
const raw = Math.round(Number(d?.value ?? 0))
const v = compactNumberFormatter.value.format(Number.isFinite(raw) ? raw : 0)

if (!hasMultipleItems) {
Expand Down
4 changes: 3 additions & 1 deletion app/components/Package/WeeklyDownloadStats.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ function handleModalTransitioned() {
}
const { fetchPackageDownloadEvolution } = useCharts()
const numberFormatter = useNumberFormatter()
const numberFormatter = useNumberFormatter({
maximumFractionDigits: 0,
})
const { accentColors, selectedAccentColor } = useAccentColor()
Expand Down
8 changes: 8 additions & 0 deletions app/composables/npm/usePackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,20 @@ export function transformPackument(
const trustLevel = getTrustLevel(version)
const hasProvenance = trustLevel !== 'none'

// Normalize license: some versions use { type: "MIT" } instead of "MIT"
let versionLicense = version.license
if (versionLicense && typeof versionLicense === 'object' && 'type' in versionLicense) {
versionLicense = (versionLicense as { type: string }).type
}

filteredVersions[v] = {
hasProvenance,
trustLevel,
version: version.version,
deprecated: version.deprecated,
tags: version.tags as string[],
license: typeof versionLicense === 'string' ? versionLicense : undefined,
type: typeof version.type === 'string' ? version.type : undefined,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/composables/useSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const DEFAULT_SETTINGS: AppSettings = {
},
chartFilter: {
averageWindow: 0,
smoothingTau: 1,
smoothingTau: 0,
anomaliesFixed: true,
predictionPoints: 4,
},
Expand Down
Loading
Loading