Skip to content

Commit ffe391a

Browse files
committed
Merge branch 'main' into feat/concept-npm-requests
2 parents adec48e + a97a7a1 commit ffe391a

234 files changed

Lines changed: 14226 additions & 3700 deletions

File tree

Some content is hidden

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

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#secure password, can use openssl rand --hex 32
1+
#secure password, can use openssl rand -hex 32
22
NUXT_SESSION_PASSWORD=""

.github/workflows/autofix.yml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ jobs:
3131
- name: 📦 Install dependencies
3232
run: pnpm install
3333

34-
- name: 📦 Install browsers
35-
run: pnpm playwright install
36-
3734
- name: 🌐 Compare translations
3835
run: pnpm i18n:check
3936

@@ -43,14 +40,4 @@ jobs:
4340
- name: 🔠 Fix lint errors
4441
run: pnpm lint:fix
4542

46-
- name: 🧪 Update unit test snapshots
47-
run: pnpm test:unit -u
48-
49-
- name: 🏃 Update component test snapshots
50-
run: pnpm test:nuxt -u
51-
52-
# TODO: re-enable when we have snapshots in browser tests
53-
# - name: 🖥️ Update browser test snapshots
54-
# run: pnpm test:browser --update-snapshots
55-
5643
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27

.github/workflows/ci.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,10 @@ jobs:
3232

3333
- uses: pnpm/action-setup@1e1c8eafbd745f64b1ef30a7d7ed7965034c486c
3434
name: Install pnpm
35-
with:
36-
cache: true
37-
38-
- name: 📦 Install dependencies
39-
run: pnpm install
35+
# pnpm cache skipped deliberately as the project is not actually installed here
4036

4137
- name: 🔠 Lint project
42-
run: pnpm lint
38+
run: node scripts/lint.ts
4339

4440
test:
4541
runs-on: ubuntu-latest
@@ -60,7 +56,7 @@ jobs:
6056
run: pnpm install
6157

6258
- name: 🌐 Install browser
63-
run: pnpm playwright install
59+
run: pnpm playwright install chromium-headless-shell
6460

6561
- name: 💪 Type check
6662
run: pnpm test:types
@@ -96,6 +92,9 @@ jobs:
9692

9793
a11y:
9894
runs-on: ubuntu-latest
95+
strategy:
96+
matrix:
97+
mode: [dark, light]
9998

10099
steps:
101100
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
@@ -115,10 +114,11 @@ jobs:
115114
- name: 🏗️ Build project
116115
run: pnpm build
117116

118-
- name: ♿ Accessibility audit (Lighthouse - dark & light mode)
117+
- name: ♿ Accessibility audit (Lighthouse - ${{ matrix.mode }} mode)
119118
run: ./scripts/lighthouse-a11y.sh
120119
env:
121120
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
121+
LIGHTHOUSE_COLOR_MODE: ${{ matrix.mode }}
122122

123123
knip:
124124
runs-on: ubuntu-latest

.github/workflows/provenance.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,28 @@ on:
44
push:
55
branches:
66
- main
7+
paths:
8+
- pnpm-lock.yaml
79
pull_request:
810
branches:
911
- main
12+
paths:
13+
- pnpm-lock.yaml
1014
merge_group:
1115
branches:
1216
- main
17+
1318
permissions:
1419
contents: read
20+
1521
jobs:
1622
check-provenance:
17-
runs-on: ubuntu-latest
23+
runs-on: ubuntu-slim
1824
steps:
1925
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2026
with:
2127
fetch-depth: 0
28+
2229
- name: Check provenance downgrades
2330
uses: danielroe/provenance-action@41bcc969e579d9e29af08ba44fcbfdf95cee6e6c # v0.1.1
2431
with:

.github/workflows/semantic-pull-requests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
1717
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
1818
if: github.repository == 'npmx-dev/npmx.dev'
19-
runs-on: ubuntu-latest
19+
runs-on: ubuntu-slim
2020
name: semantic-pr
2121
steps:
2222
- name: Validate PR title

.lighthouserc.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module.exports = {
2929
url: [
3030
'http://localhost:3000/',
3131
'http://localhost:3000/search?q=nuxt',
32-
'http://localhost:3000/nuxt',
32+
'http://localhost:3000/package/nuxt',
3333
],
3434
numberOfRuns: 1,
3535
chromePath: findChrome(),

CONTRIBUTING.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,43 @@ We want to create 'a fast, modern browser for the npm registry.' This means, amo
1414
- Layout shift, flakiness, slowness is The Worst. We need to continually iterate to create the most performant, best DX possible.
1515
- We want to provide information in the best way. We don't want noise, cluttered display, or confusing UI. If in doubt: choose simplicity.
1616

17+
## Table of Contents
18+
19+
- [Getting started](#getting-started)
20+
- [Prerequisites](#prerequisites)
21+
- [Setup](#setup)
22+
- [Development workflow](#development-workflow)
23+
- [Available commands](#available-commands)
24+
- [Project structure](#project-structure)
25+
- [Local connector CLI](#local-connector-cli)
26+
- [Code style](#code-style)
27+
- [TypeScript](#typescript)
28+
- [Server API patterns](#server-api-patterns)
29+
- [Import order](#import-order)
30+
- [Naming conventions](#naming-conventions)
31+
- [Vue components](#vue-components)
32+
- [RTL Support](#rtl-support)
33+
- [Localization (i18n)](#localization-i18n)
34+
- [Approach](#approach)
35+
- [Adding a new locale](#adding-a-new-locale)
36+
- [Update translation](#update-translation)
37+
- [Adding translations](#adding-translations)
38+
- [Translation key conventions](#translation-key-conventions)
39+
- [Using i18n-ally (recommended)](#using-i18n-ally-recommended)
40+
- [Formatting numbers and dates](#formatting-numbers-and-dates)
41+
- [Testing](#testing)
42+
- [Unit tests](#unit-tests)
43+
- [Component accessibility tests](#component-accessibility-tests)
44+
- [End to end tests](#end-to-end-tests)
45+
- [Submitting changes](#submitting-changes)
46+
- [Before submitting](#before-submitting)
47+
- [Pull request process](#pull-request-process)
48+
- [Commit messages and PR titles](#commit-messages-and-pr-titles)
49+
- [Pre-commit hooks](#pre-commit-hooks)
50+
- [Using AI](#using-ai)
51+
- [Questions](#questions)
52+
- [License](#license)
53+
1754
## Getting started
1855

1956
### Prerequisites
@@ -111,7 +148,7 @@ To help with this, the project uses `oxfmt` to handle formatting via a pre-commi
111148

112149
If you want to get ahead of any formatting issues, you can also run `pnpm lint:fix` before committing to fix formatting across the whole project.
113150

114-
### Typescript
151+
### TypeScript
115152

116153
- We care about good types – never cast things to `any` 💪
117154
- Validate rather than just assert
@@ -485,6 +522,31 @@ Format: `type(scope): description`
485522
> [!NOTE]
486523
> The subject must start with a lowercase letter. Individual commit messages within your PR don't need to follow this format since they'll be squashed.
487524
525+
### PR descriptions
526+
527+
If your pull request directly addresses an open issue, use the following inside your PR description.
528+
529+
```text
530+
Resolves | Fixes | Closes: #xxx
531+
```
532+
533+
Replace `#xxx` with either a URL to the issue, or the number of the issue. For example:
534+
535+
```text
536+
Fixes #123
537+
```
538+
539+
or
540+
541+
```text
542+
Closes https://github.com/npmx-dev/npmx.dev/issues/123
543+
```
544+
545+
This provides the following benefits:
546+
547+
- it links the pull request to the issue (the merge icon will appear in the issue), so everybody can see there is an open PR
548+
- when the pull request is merged, the linked issue is automatically closed
549+
488550
## Pre-commit hooks
489551

490552
The project uses `lint-staged` with `simple-git-hooks` to automatically lint files on commit.

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@
1313

1414
## Vision
1515

16-
The aim of [npmx.dev](https://npmx.dev) is to provide a better browser for the npm registry – fast, modern, and accessible. We don't aim to replace the [npmjs.com](https://www.npmjs.com/) registry, just provide a better UI, DX, and admin experience.
16+
The goal of [npmx.dev](https://npmx.dev) is to build a fast, modern browser for the npm registry.
1717

18-
- **Speed first** – Layout shift, flakiness, slowness is The Worst. Fast searching, filtering, and navigation.
19-
- **URL compatible** – Replace `npmjs.com` with `xnpmjs.com` or `npmx.dev` in any URL and it just works.
20-
- **Simplicity** – No noise, cluttered display, or confusing UI. If in doubt: choose simplicity.
21-
- **Admin UI** – Manage your packages, teams, and organizations from the browser, powered by your local npm CLI.
18+
We're not replacing the [npmjs.com](https://www.npmjs.com/) registry, but instead providing an elevated developer experience through a fast, modern UI.
19+
20+
What npmx offers:
21+
22+
- **Speed** – Fast searching, filtering, and navigation.
23+
- **Simplicity** – Get the information you need when you need it in an intuitive UI.
24+
- **Compatibility** – Replace `npmjs.com` with `xnpmjs.com` or `npmx.dev` in any URL and it just works.
25+
- **Enhanced admin experience** – Manage your packages, teams, and organizations from the browser, powered by your local npm CLI.
2226

2327
## Shortcuts
2428

@@ -36,7 +40,7 @@ The aim of [npmx.dev](https://npmx.dev) is to provide a better browser for the n
3640

3741
### Package browsing
3842

39-
- **Dark mode by default** – easier on the eyes
43+
- **Dark mode and light mode** – plus customize the color palette to your preferences
4044
- **Fast search** – quick package search with instant results
4145
- **Package details** – READMEs, versions, dependencies, and metadata
4246
- **Code viewer** – browse package source code with syntax highlighting and permalink to specific lines
@@ -100,7 +104,7 @@ The aim of [npmx.dev](https://npmx.dev) is to provide a better browser for the n
100104

101105
### npm compatibility
102106

103-
npmx.dev supports npm permalinks – just replace `npmjs.com` with `npmx.dev` or `xnpmjs.com` and it works:
107+
npmx.dev supports npm permalinks – just replace `npmjs.com` with `npmx.dev` or `xnpmjs.com` to get the npmx experience:
104108

105109
| npm URL | npmx.dev equivalent |
106110
| ------------------------------- | ---------------------------------------------------------------------- |
@@ -142,7 +146,7 @@ npmx.dev also supports shorter, cleaner URLs:
142146

143147
## Contributing
144148

145-
We welcome contributions – please do feel free to poke around and improve things. See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to get up and running!
149+
We welcome contributions – please do feel free to explore the project and improve things. See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to get up and running!
146150

147151
## Related projects
148152

@@ -151,6 +155,7 @@ We welcome contributions – please do feel free to poke around and improve
151155
- [npm-userscript](https://github.com/bluwy/npm-userscript) – Browser userscript with various improvements and fixes for npmjs.com
152156
- [npm-alt](https://npm.willow.sh/) – An alternative npm package browser
153157
- [npkg.lorypelli.dev](https://npkg.lorypelli.dev/) – An alternative frontend to npm made with as little client-side JavaScript as possible
158+
- [vscode-npmx](https://github.com/npmx-dev/vscode-npmx) – VSCode extension for npmx
154159

155160
If you're building something cool, let us know! 🙏
156161

app/app.vue

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ const localeMap = locales.value.reduce(
2121
{} as Record<string, Directions>,
2222
)
2323
24+
const darkMode = usePreferredDark()
25+
const colorMode = useColorMode()
26+
const colorScheme = computed(() => {
27+
return {
28+
system: darkMode ? 'dark light' : 'light dark',
29+
light: 'only light',
30+
dark: 'only dark',
31+
}[colorMode.preference]
32+
})
33+
2434
useHead({
2535
htmlAttrs: {
2636
'lang': () => locale.value,
@@ -30,6 +40,7 @@ useHead({
3040
titleTemplate: titleChunk => {
3141
return titleChunk ? titleChunk : 'npmx - Better npm Package Browser'
3242
},
43+
meta: [{ name: 'color-scheme', content: colorScheme }],
3344
})
3445
3546
if (import.meta.server) {
@@ -58,7 +69,8 @@ function handleGlobalKeydown(e: KeyboardEvent) {
5869
router.push('/search')
5970
}
6071
61-
if (isKeyWithoutModifiers(e, '?')) {
72+
// For "?" we check the key property directly since it's usually combined with shift
73+
if (e.key === '?') {
6274
e.preventDefault()
6375
showKbdHints.value = true
6476
}
@@ -68,20 +80,37 @@ function handleGlobalKeyup() {
6880
showKbdHints.value = false
6981
}
7082
71-
/* A hack to get light dismiss to work in safari because it does not support closedby="any" yet */
83+
// Light dismiss fallback for browsers that don't support closedby="any" (Safari + old Chrome/Firefox)
7284
// https://codepen.io/paramagicdev/pen/gbYompq
7385
// see: https://github.com/npmx-dev/npmx.dev/pull/522#discussion_r2749978022
7486
function handleModalLightDismiss(e: MouseEvent) {
7587
const target = e.target as HTMLElement
7688
if (target.tagName === 'DIALOG' && target.hasAttribute('open')) {
89+
const rect = target.getBoundingClientRect()
90+
const isOutside =
91+
e.clientX < rect.left ||
92+
e.clientX > rect.right ||
93+
e.clientY < rect.top ||
94+
e.clientY > rect.bottom
95+
96+
if (!isOutside) return
7797
;(target as HTMLDialogElement).close()
7898
}
7999
}
80100
81101
if (import.meta.client) {
82102
useEventListener(document, 'keydown', handleGlobalKeydown)
83103
useEventListener(document, 'keyup', handleGlobalKeyup)
84-
useEventListener(document, 'click', handleModalLightDismiss)
104+
105+
// Feature check for native light dismiss support via closedby="any"
106+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby
107+
const supportsClosedBy =
108+
typeof HTMLDialogElement !== 'undefined' &&
109+
typeof HTMLDialogElement.prototype === 'object' &&
110+
'closedBy' in HTMLDialogElement.prototype
111+
if (!supportsClosedBy) {
112+
useEventListener(document, 'click', handleModalLightDismiss)
113+
}
85114
}
86115
</script>
87116

0 commit comments

Comments
 (0)