Skip to content

Commit b0a3548

Browse files
Merge branch 'main' into fix/header-nav-i18n-and-settings-icon
2 parents 9b2c854 + e331d86 commit b0a3548

File tree

11 files changed

+127
-26
lines changed

11 files changed

+127
-26
lines changed

.storybook/handlers.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,37 @@ export const contributorsHandler = http.get('/api/contributors', () => {
5757
},
5858
])
5959
})
60+
61+
export const pdsUsersHandler = http.get('/api/atproto/pds-users', () => {
62+
return HttpResponse.json([
63+
{
64+
did: 'did:plc:mock0001',
65+
handle: 'patak.dog',
66+
displayName: 'Patak Dog',
67+
avatar:
68+
'https://cdn.bsky.app/img/avatar/plain/did:plc:zjfptjaegvgc7r2axkkyyzqn/bafkreihrcqhp575f6dph4uztbeyxfrmfnbv7x2gvovrgu4idgdsdw7wety',
69+
},
70+
{
71+
did: 'did:plc:mock0002',
72+
handle: 'patakllama.mockpmx.social',
73+
displayName: 'Patak Llama',
74+
avatar: 'https://api.dicebear.com/9.x/initials/svg?seed=llama',
75+
},
76+
{
77+
did: 'did:plc:mock0003',
78+
handle: 'patak.horse',
79+
displayName: 'Patak Horse',
80+
avatar:
81+
'https://cdn.bsky.app/img/avatar/plain/did:plc:vqh7id7sddkrfkhgt7tstlpd/bafkreifodkgqszgpt2qnoyljnbafokr6eujqwztj2kxo473adv5b57hjse',
82+
},
83+
{
84+
did: 'did:plc:mock0004',
85+
handle: 'patakcatapiller.mockpmx.social',
86+
},
87+
{
88+
did: 'did:plc:mock0005',
89+
handle: 'patakgoat.mockpmx.social',
90+
displayName: 'Patak Goat',
91+
},
92+
])
93+
})

app/components/Package/WeeklyDownloadStats.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ function handleModalTransitioned() {
6060
}
6161
6262
const { fetchPackageDownloadEvolution } = useCharts()
63+
const numberFormatter = useNumberFormatter()
6364
6465
const { accentColors, selectedAccentColor } = useAccentColor()
6566
@@ -359,6 +360,9 @@ const config = computed<VueUiSparklineConfig>(() => {
359360
fontSize: 28,
360361
bold: false,
361362
color: colors.value.fg,
363+
formatter: ({ value }) => {
364+
return numberFormatter.value.format(value)
365+
},
362366
},
363367
line: {
364368
color: colors.value.borderHover,

app/components/Readme.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ function handleClick(event: MouseEvent) {
8989
min-width: 0;
9090
/* Contain all children z-index values inside this container */
9191
isolation: isolate;
92+
contain: layout paint;
9293
}
9394
9495
/* README headings - styled by visual level (data-level), not semantic level */

app/components/Tab/Panel.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const resolvedTabId = computed(() => getTabId(props.value))
2121

2222
<template>
2323
<div
24-
v-show="isSelected"
24+
v-if="isSelected"
2525
:id="resolvedPanelId"
2626
role="tabpanel"
2727
:aria-labelledby="resolvedTabId"

app/composables/npm/useAlgoliaSearch.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ export function useAlgoliaSearch() {
161161
}
162162
}
163163

164-
/** Fetch all packages for an owner using `owner.name` filter with pagination. */
165-
async function searchByOwner(
164+
/** Fetch all packages for a maintainer using `owners.name` filter with pagination. */
165+
async function searchByMaintainer(
166166
ownerName: string,
167167
options: { maxResults?: number } = {},
168168
): Promise<NpmSearchResponse> {
@@ -185,7 +185,7 @@ export function useAlgoliaSearch() {
185185
query: '',
186186
offset,
187187
length,
188-
filters: `owner.name:${ownerName}`,
188+
filters: `owners.name:${ownerName}`,
189189
analyticsTags: ['npmx.dev'],
190190
attributesToRetrieve: ATTRIBUTES_TO_RETRIEVE,
191191
attributesToHighlight: [],
@@ -286,7 +286,7 @@ export function useAlgoliaSearch() {
286286
requests.push({
287287
indexName,
288288
query: '',
289-
filters: `owner.name:${checks.name}`,
289+
filters: `owners.name:${checks.name}`,
290290
length: 1,
291291
analyticsTags: ['npmx.dev'],
292292
attributesToRetrieve: EXISTENCE_CHECK_ATTRS,
@@ -347,7 +347,7 @@ export function useAlgoliaSearch() {
347347
return {
348348
search,
349349
searchWithSuggestions,
350-
searchByOwner,
350+
searchByMaintainer,
351351
getPackagesByName,
352352
}
353353
}

app/composables/npm/useUserPackages.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function useUserPackages(username: MaybeRefOrGetter<string>) {
2828
})
2929
// this is only used in npm path, but we need to extract it when the composable runs
3030
const { $npmRegistry } = useNuxtApp()
31-
const { searchByOwner } = useAlgoliaSearch()
31+
const { searchByMaintainer } = useAlgoliaSearch()
3232

3333
// --- Incremental loading state (npm path) ---
3434
const currentPage = shallowRef(1)
@@ -58,7 +58,7 @@ export function useUserPackages(username: MaybeRefOrGetter<string>) {
5858
// --- Algolia: fetch all at once ---
5959
if (provider === 'algolia') {
6060
try {
61-
const response = await searchByOwner(user)
61+
const response = await searchByMaintainer(user)
6262

6363
// Guard against stale response (user/provider changed during await)
6464
if (user !== toValue(username) || provider !== searchProviderValue.value) {

app/composables/useSelectedPackageManager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export const useSelectedPackageManager = createSharedComposable(
1212

1313
// Sync to data-pm attribute on the client
1414
if (import.meta.client) {
15+
const queryPM = new URLSearchParams(window.location.search).get('pm')
16+
if (queryPM && packageManagers.some(pm => pm.id === queryPM)) {
17+
pm.value = queryPM as PackageManagerId
18+
}
1519
// Watch for changes and update the attribute
1620
watch(
1721
pm,

app/pages/pds.stories.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Pds from './pds.vue'
2+
import type { Meta, StoryObj } from '@storybook-vue/nuxt'
3+
import { pageDecorator } from '../../.storybook/decorators'
4+
import { pdsUsersHandler } from '../../.storybook/handlers'
5+
6+
const meta = {
7+
component: Pds,
8+
parameters: {
9+
layout: 'fullscreen',
10+
msw: {
11+
handlers: [pdsUsersHandler],
12+
},
13+
},
14+
decorators: [pageDecorator],
15+
} satisfies Meta<typeof Pds>
16+
17+
export default meta
18+
type Story = StoryObj<typeof meta>
19+
20+
/** `/api/atproto/pds-users` is intercepted by MSW so the community section displays both avatar images and text-only entries. */
21+
export const Default: Story = {}
22+
23+
/** Community section shows an empty/loading state with no API response. */
24+
export const WithoutUsers: Story = {
25+
parameters: {
26+
msw: {
27+
handlers: [],
28+
},
29+
},
30+
}

app/utils/prehydrate.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,28 @@ export function initPreferencesOnPrehydrate() {
3939
document.documentElement.dataset.bgTheme = preferredBackgroundTheme
4040
}
4141

42-
// Read and apply package manager preference
43-
const storedPM = localStorage.getItem('npmx-pm')
44-
// Parse the stored value (it's stored as a JSON string by useLocalStorage)
4542
let pm = 'npm'
46-
if (storedPM) {
47-
try {
48-
const parsed = JSON.parse(storedPM)
49-
if (validPMs.has(parsed)) {
50-
pm = parsed
51-
}
52-
} catch {
53-
// If parsing fails, check if it's a plain string (legacy format)
54-
if (validPMs.has(storedPM)) {
55-
pm = storedPM
43+
44+
// Support package manager preference in query string (for example, ?pm=pnpm)
45+
const queryPM = new URLSearchParams(window.location.search).get('pm')
46+
if (queryPM && validPMs.has(queryPM)) {
47+
pm = queryPM
48+
localStorage.setItem('npmx-pm', pm)
49+
} else {
50+
// Read and apply package manager preference
51+
const storedPM = localStorage.getItem('npmx-pm')
52+
// Parse the stored value (it's stored as a JSON string by useLocalStorage)
53+
if (storedPM) {
54+
try {
55+
const parsed = JSON.parse(storedPM)
56+
if (validPMs.has(parsed)) {
57+
pm = parsed
58+
}
59+
} catch {
60+
// If parsing fails, check if it's a plain string (legacy format)
61+
if (validPMs.has(storedPM)) {
62+
pm = storedPM
63+
}
5664
}
5765
}
5866
}

i18n/locales/zh-CN.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@
280280
"black": "黑色"
281281
},
282282
"keyboard_shortcuts_enabled": "启用快捷键",
283-
"keyboard_shortcuts_enabled_description": "如果某些快捷键与其他浏览器或系统快捷键冲突,可以选择将其禁用。"
283+
"keyboard_shortcuts_enabled_description": "如果某些快捷键与其他浏览器或系统快捷键冲突,可以选择将其禁用。",
284+
"enable_code_ligatures": "在代码中启用连字"
284285
},
285286
"i18n": {
286287
"missing_keys": "{count} 项缺少翻译",
@@ -1325,6 +1326,18 @@
13251326
"vulnerabilities": {
13261327
"label": "漏洞",
13271328
"description": "已知安全漏洞"
1329+
},
1330+
"githubStars": {
1331+
"label": "GitHub 星标",
1332+
"description": "GitHub 仓库的星标数量"
1333+
},
1334+
"githubIssues": {
1335+
"label": "GitHub 问题数",
1336+
"description": "GitHub 仓库的问题数量"
1337+
},
1338+
"createdAt": {
1339+
"label": "创建时间",
1340+
"description": "包创建时间"
13281341
}
13291342
},
13301343
"values": {

0 commit comments

Comments
 (0)