Skip to content

Commit c8887e6

Browse files
authored
Merge branch 'main' into use-setup-vp-instead
2 parents e990bec + 84a7fc9 commit c8887e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2257
-2677
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: welcome
1+
name: Claim Contributor Message
22

33
on:
44
pull_request_target:

.github/workflows/welcome-open.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Welcome Message
2+
3+
on:
4+
pull_request_target:
5+
branches: [main]
6+
types: [opened]
7+
8+
permissions:
9+
pull-requests: write
10+
11+
jobs:
12+
greeting:
13+
name: Greet First-Time Contributors
14+
if: github.repository == 'npmx-dev/npmx.dev'
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: zephyrproject-rtos/action-first-interaction@58853996b1ac504b8e0f6964301f369d2bb22e5c
18+
with:
19+
pr-opened-message: |
20+
Hello! Thank you for opening your **first PR** to npmx, @${{ github.event.pull_request.user.login }}! 🚀
21+
22+
Here’s what will happen next:
23+
24+
1. Our GitHub bots will run to check your changes.
25+
If they spot any issues you will see some error messages on this PR.
26+
Don’t hesitate to ask any questions if you’re not sure what these mean!
27+
28+
2. In a few minutes, you’ll be able to see a preview of your changes on Vercel
29+
30+
3. One or more of our maintainers will take a look and may ask you to make changes.
31+
We try to be responsive, but don’t worry if this takes a few days.

CONTRIBUTING.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,23 @@ pnpm test:browser:ui # Run with Playwright UI
752752

753753
Make sure to read about [Playwright best practices](https://playwright.dev/docs/best-practices) and don't rely on classes/IDs but try to follow user-replicable behaviour (like selecting an element based on text content instead).
754754

755+
#### Updating snapshots
756+
757+
Some tests use image snapshots that must match the CI environment (Linux). If you need to update them, and aren't running Linux, you can use Docker to run in the same environment:
758+
759+
```bash
760+
docker run --rm \
761+
-e CI=true \
762+
-e NODE_OPTIONS="--max-old-space-size=4096" \
763+
-v $(pwd):/work \
764+
-w /work \
765+
mcr.microsoft.com/playwright:v1.58.2-noble \
766+
sh -c "npm install -g pnpm && pnpm install && pnpm vp run build:test && pnpm vp run test:browser:prebuilt --update-snapshots"
767+
```
768+
769+
> [!NOTE]
770+
> If the build runs out of memory, increase `--max-old-space-size` to `8192`.
771+
755772
### Test fixtures (mocking external APIs)
756773

757774
E2E tests use a fixture system to mock external API requests, ensuring tests are deterministic and don't hit real APIs. This is handled at two levels:

app/components/ColumnPicker.vue

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ const columnLabels = computed(() => ({
4949
updated: $t('filters.columns.published'),
5050
maintainers: $t('filters.columns.maintainers'),
5151
keywords: $t('filters.columns.keywords'),
52-
qualityScore: $t('filters.columns.quality_score'),
53-
popularityScore: $t('filters.columns.popularity_score'),
54-
maintenanceScore: $t('filters.columns.maintenance_score'),
55-
combinedScore: $t('filters.columns.combined_score'),
5652
security: $t('filters.columns.security'),
5753
selection: $t('filters.columns.selection'),
5854
}))

app/components/Package/List.vue

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ watch(
112112
{ immediate: true },
113113
)
114114
115+
// Tracks how many items came from the last new-search batch.
116+
// Items at index < newSearchBatchSize are from the new search → no animation.
117+
// Items at index >= newSearchBatchSize were loaded via scroll → animate with stagger.
118+
// Using an index threshold avoids any timing dependency on nextTick / virtual list paint.
119+
const newSearchBatchSize = shallowRef(Infinity)
120+
115121
// Reset scroll state when results change significantly (new search)
116122
watch(
117123
() => props.results,
@@ -123,6 +129,7 @@ watch(
123129
(oldResults.length > 0 && newResults[0]?.package.name !== oldResults[0]?.package.name)
124130
) {
125131
hasScrolledToInitial.value = false
132+
newSearchBatchSize.value = newResults.length
126133
}
127134
},
128135
)
@@ -172,9 +179,16 @@ defineExpose({
172179
:show-publisher="showPublisher"
173180
:index="index"
174181
:search-query="searchQuery"
175-
class="motion-safe:animate-fade-in motion-safe:animate-fill-both"
182+
:class="
183+
index >= newSearchBatchSize &&
184+
'motion-safe:animate-fade-in motion-safe:animate-fill-both'
185+
"
186+
:style="
187+
index >= newSearchBatchSize
188+
? { animationDelay: `${Math.min((index - newSearchBatchSize) * 0.02, 0.3)}s` }
189+
: {}
190+
"
176191
:filters="filters"
177-
:style="{ animationDelay: `${Math.min(index * 0.02, 0.3)}s` }"
178192
@click-keyword="emit('clickKeyword', $event)"
179193
/>
180194
</div>
@@ -224,8 +238,15 @@ defineExpose({
224238
:show-publisher="showPublisher"
225239
:index="index"
226240
:search-query="searchQuery"
227-
class="motion-safe:animate-fade-in motion-safe:animate-fill-both"
228-
:style="{ animationDelay: `${Math.min(index * 0.02, 0.3)}s` }"
241+
:class="
242+
index >= newSearchBatchSize &&
243+
'motion-safe:animate-fade-in motion-safe:animate-fill-both'
244+
"
245+
:style="
246+
index >= newSearchBatchSize
247+
? { animationDelay: `${Math.min((index - newSearchBatchSize) * 0.02, 0.3)}s` }
248+
: {}
249+
"
229250
:filters="filters"
230251
@click-keyword="emit('clickKeyword', $event)"
231252
/>

app/components/Package/ListToolbar.vue

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,6 @@ const sortKeyLabelKeys = computed<Record<SortKey, string>>(() => ({
102102
'downloads-year': t('filters.sort.downloads_year'),
103103
'updated': t('filters.sort.published'),
104104
'name': t('filters.sort.name'),
105-
'quality': t('filters.sort.quality'),
106-
'popularity': t('filters.sort.popularity'),
107-
'maintenance': t('filters.sort.maintenance'),
108-
'score': t('filters.sort.score'),
109105
}))
110106
111107
function getSortKeyLabelKey(key: SortKey): string {

app/components/Package/Table.vue

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,13 @@ const columnToSortKey: Record<string, SortKey> = {
3737
name: 'name',
3838
downloads: 'downloads-week',
3939
updated: 'updated',
40-
qualityScore: 'quality',
41-
popularityScore: 'popularity',
42-
maintenanceScore: 'maintenance',
43-
combinedScore: 'score',
4440
}
4541
4642
// Default direction for each column
4743
const columnDefaultDirection: Record<string, 'asc' | 'desc'> = {
4844
name: 'asc',
4945
downloads: 'desc',
5046
updated: 'desc',
51-
qualityScore: 'desc',
52-
popularityScore: 'desc',
53-
maintenanceScore: 'desc',
54-
combinedScore: 'desc',
5547
}
5648
5749
function isColumnSorted(id: string): boolean {
@@ -97,10 +89,6 @@ const columnLabels = computed(() => ({
9789
updated: t('filters.columns.published'),
9890
maintainers: t('filters.columns.maintainers'),
9991
keywords: t('filters.columns.keywords'),
100-
qualityScore: t('filters.columns.quality_score'),
101-
popularityScore: t('filters.columns.popularity_score'),
102-
maintenanceScore: t('filters.columns.maintenance_score'),
103-
combinedScore: t('filters.columns.combined_score'),
10492
security: t('filters.columns.security'),
10593
selection: t('filters.columns.selection'),
10694
}))
@@ -264,38 +252,6 @@ function getColumnLabel(id: ColumnId): string {
264252
{{ getColumnLabel('keywords') }}
265253
</th>
266254

267-
<th
268-
v-if="isColumnVisible('qualityScore')"
269-
scope="col"
270-
class="py-3 px-3 text-xs text-start text-fg-muted font-mono font-medium uppercase tracking-wider whitespace-nowrap select-none text-end"
271-
>
272-
{{ getColumnLabel('qualityScore') }}
273-
</th>
274-
275-
<th
276-
v-if="isColumnVisible('popularityScore')"
277-
scope="col"
278-
class="py-3 px-3 text-xs text-start text-fg-muted font-mono font-medium uppercase tracking-wider whitespace-nowrap select-none text-end"
279-
>
280-
{{ getColumnLabel('popularityScore') }}
281-
</th>
282-
283-
<th
284-
v-if="isColumnVisible('maintenanceScore')"
285-
scope="col"
286-
class="py-3 px-3 text-xs text-start text-fg-muted font-mono font-medium uppercase tracking-wider whitespace-nowrap select-none text-end"
287-
>
288-
{{ getColumnLabel('maintenanceScore') }}
289-
</th>
290-
291-
<th
292-
v-if="isColumnVisible('combinedScore')"
293-
scope="col"
294-
class="py-3 px-3 text-xs text-start text-fg-muted font-mono font-medium uppercase tracking-wider whitespace-nowrap select-none text-end"
295-
>
296-
{{ getColumnLabel('combinedScore') }}
297-
</th>
298-
299255
<th
300256
v-if="isColumnVisible('security')"
301257
scope="col"

app/components/Package/TableRow.vue

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,13 @@ const emit = defineEmits<{
1414
}>()
1515
1616
const pkg = computed(() => props.result.package)
17-
const score = computed(() => props.result.score)
1817
1918
const updatedDate = computed(() => props.result.package.date)
2019
const { isPackageSelected, togglePackageSelection, canSelectMore } = usePackageSelection()
2120
const isSelected = computed<boolean>(() => {
2221
return isPackageSelected(props.result.package.name)
2322
})
2423
25-
function formatScore(value?: number): string {
26-
if (value === undefined || value === 0) return '-'
27-
return Math.round(value * 100).toString()
28-
}
29-
3024
function isColumnVisible(id: string): boolean {
3125
return props.columns.find(c => c.id === id)?.visible ?? false
3226
}
@@ -163,38 +157,6 @@ const compactNumberFormatter = useCompactNumberFormatter()
163157
<span v-else class="text-fg-subtle">-</span>
164158
</td>
165159

166-
<!-- Quality Score -->
167-
<td
168-
v-if="isColumnVisible('qualityScore')"
169-
class="py-2 px-3 font-mono text-xs text-fg-muted text-end tabular-nums"
170-
>
171-
{{ formatScore(score?.detail?.quality) }}
172-
</td>
173-
174-
<!-- Popularity Score -->
175-
<td
176-
v-if="isColumnVisible('popularityScore')"
177-
class="py-2 px-3 font-mono text-xs text-fg-muted text-end tabular-nums"
178-
>
179-
{{ formatScore(score?.detail?.popularity) }}
180-
</td>
181-
182-
<!-- Maintenance Score -->
183-
<td
184-
v-if="isColumnVisible('maintenanceScore')"
185-
class="py-2 px-3 font-mono text-xs text-fg-muted text-end tabular-nums"
186-
>
187-
{{ formatScore(score?.detail?.maintenance) }}
188-
</td>
189-
190-
<!-- Combined Score -->
191-
<td
192-
v-if="isColumnVisible('combinedScore')"
193-
class="py-2 px-3 font-mono text-xs text-fg-muted text-end tabular-nums"
194-
>
195-
{{ formatScore(score?.final) }}
196-
</td>
197-
198160
<!-- Security -->
199161
<td v-if="isColumnVisible('security')" class="py-2 px-3">
200162
<span v-if="result.flags?.insecure" class="text-syntax-kw">

app/composables/npm/search-utils.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export function metaToSearchResult(meta: PackageMetaResponse): NpmSearchResult {
1111
author: meta.author,
1212
maintainers: meta.maintainers,
1313
},
14-
score: { final: 0, detail: { quality: 0, popularity: 0, maintenance: 0 } },
1514
searchScore: 0,
1615
downloads: meta.weeklyDownloads !== undefined ? { weekly: meta.weeklyDownloads } : undefined,
1716
updated: meta.date,

app/composables/npm/useAlgoliaSearch.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,6 @@ function hitToSearchResult(hit: AlgoliaHit): NpmSearchResult {
9191
}))
9292
: [],
9393
},
94-
score: {
95-
final: 0,
96-
detail: {
97-
quality: hit.popular ? 1 : 0,
98-
popularity: hit.downloadsRatio,
99-
maintenance: 0,
100-
},
101-
},
10294
searchScore: 0,
10395
downloads: {
10496
weekly: Math.round(hit.downloadsLast30Days / 4.3),

0 commit comments

Comments
 (0)