Skip to content

Commit 87dc65b

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix/proxy-readme-images-privacy
2 parents ffc0b5e + 77fd97e commit 87dc65b

File tree

205 files changed

+9333
-6502
lines changed

Some content is hidden

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

205 files changed

+9333
-6502
lines changed

.github/workflows/autofix.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ jobs:
3232
- name: 📦 Install dependencies
3333
run: pnpm install
3434

35-
- name: 🎨 Check for non-RTL CSS classes
36-
run: pnpm rtl:check
35+
- name: 🎨 Check for non-RTL/non-a11y CSS classes
36+
run: pnpm lint:css
3737

3838
- name: 🌐 Compare translations
3939
run: pnpm i18n:check

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
run: pnpm install
8585

8686
- name: 🧪 Unit tests
87-
run: pnpm test:unit run --coverage --reporter=junit --outputFile=test-report.junit.xml
87+
run: pnpm test:unit run --coverage --reporter=default --reporter=junit --outputFile=test-report.junit.xml
8888

8989
- name: ⬆︎ Upload test results to Codecov
9090
if: ${{ !cancelled() }}
@@ -115,7 +115,7 @@ jobs:
115115
run: pnpm playwright install chromium-headless-shell
116116

117117
- name: 🧪 Component tests
118-
run: pnpm test:nuxt run --coverage --reporter=junit --outputFile=test-report.junit.xml
118+
run: pnpm test:nuxt run --coverage --reporter=default --reporter=junit --outputFile=test-report.junit.xml
119119

120120
- name: ⬆︎ Upload coverage reports to Codecov
121121
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5
@@ -184,7 +184,7 @@ jobs:
184184
run: pnpm build:test
185185

186186
- name: ♿ Accessibility audit (Lighthouse - ${{ matrix.mode }} mode)
187-
run: ./scripts/lighthouse-a11y.sh
187+
run: pnpm test:a11y:prebuilt
188188
env:
189189
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
190190
LIGHTHOUSE_COLOR_MODE: ${{ matrix.mode }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,7 @@ test-results/
4040
# generated files
4141
shared/types/lexicons
4242

43+
**/__screenshots__/**
44+
4345
# output
4446
.vercel

.nuxtrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
setups.@nuxt/test-utils="3.23.0"
1+
setups.@nuxt/test-utils="4.0.0"

CONTRIBUTING.md

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ This focus helps guide our project decisions as a community and what we choose t
4343
- [RTL Support](#rtl-support)
4444
- [Localization (i18n)](#localization-i18n)
4545
- [Approach](#approach)
46+
- [i18n commands](#i18n-commands)
4647
- [Adding a new locale](#adding-a-new-locale)
4748
- [Update translation](#update-translation)
4849
- [Adding translations](#adding-translations)
@@ -52,6 +53,7 @@ This focus helps guide our project decisions as a community and what we choose t
5253
- [Testing](#testing)
5354
- [Unit tests](#unit-tests)
5455
- [Component accessibility tests](#component-accessibility-tests)
56+
- [Lighthouse accessibility tests](#lighthouse-accessibility-tests)
5557
- [End to end tests](#end-to-end-tests)
5658
- [Test fixtures (mocking external APIs)](#test-fixtures-mocking-external-apis)
5759
- [Submitting changes](#submitting-changes)
@@ -111,6 +113,7 @@ pnpm test # Run all Vitest tests
111113
pnpm test:unit # Unit tests only
112114
pnpm test:nuxt # Nuxt component tests
113115
pnpm test:browser # Playwright E2E tests
116+
pnpm test:a11y # Lighthouse accessibility audits
114117
```
115118

116119
### Project structure
@@ -378,6 +381,17 @@ npmx.dev uses [@nuxtjs/i18n](https://i18n.nuxtjs.org/) for internationalization.
378381
- We use the `no_prefix` strategy (no `/en-US/` or `/fr-FR/` in URLs)
379382
- Locale preference is stored in cookies and respected on subsequent visits
380383

384+
### i18n commands
385+
386+
The following scripts help manage translation files. `en.json` is the reference locale.
387+
388+
| Command | Description |
389+
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
390+
| `pnpm i18n:check [locale]` | Compares `en.json` with other locale files. Shows missing and extra keys. Optionally filter output by locale (e.g. `pnpm i18n:check ja-JP`). |
391+
| `pnpm i18n:check:fix [locale]` | Same as check, but adds missing keys to other locales with English placeholders. |
392+
| `pnpm i18n:report` | Audits translation keys against code usage in `.vue` and `.ts` files. Reports missing keys (used in code but not in locale), unused keys (in locale but not in code), and dynamic keys. |
393+
| `pnpm i18n:report:fix` | Removes unused keys from `en.json` and all other locale files. |
394+
381395
### Adding a new locale
382396

383397
We are using localization using country variants (ISO-6391) via [multiple translation files](https://i18n.nuxtjs.org/docs/guide/lazy-load-translations#multiple-files-lazy-loading) to avoid repeating every key per country.
@@ -421,25 +435,7 @@ Check [Pluralization rule callback](https://vue-i18n.intlify.dev/guide/essential
421435
We track the current progress of translations with [Lunaria](https://lunaria.dev/) on this site: https://i18n.npmx.dev/
422436
If you see any outdated translations in your language, feel free to update the keys to match the English version.
423437

424-
In order to make sure you have everything up-to-date, you can run:
425-
426-
```bash
427-
pnpm i18n:check <country-code>
428-
```
429-
430-
For example to check if all Japanese translation keys are up-to-date, run:
431-
432-
```bash
433-
pnpm i18n:check ja-JP
434-
```
435-
436-
To automatically add missing keys with English placeholders, use `--fix`:
437-
438-
```bash
439-
pnpm i18n:check:fix fr-FR
440-
```
441-
442-
This will add missing keys with `"EN TEXT TO REPLACE: {english text}"` as placeholder values, making it easier to see what needs translation.
438+
Use `pnpm i18n:check` and `pnpm i18n:check:fix` to verify and fix your locale (see [i18n commands](#i18n-commands) above for details).
443439

444440
#### Country variants (advanced)
445441

@@ -527,6 +523,32 @@ See how `es`, `es-ES`, and `es-419` are configured in [config/i18n.ts](./config/
527523
- Use `common.*` for shared strings (loading, retry, close, etc.)
528524
- Use component-specific prefixes: `package.card.*`, `settings.*`, `nav.*`
529525
- Do not use dashes (`-`) in translation keys; always use underscore (`_`): e.g., `privacy_policy` instead of `privacy-policy`
526+
- **Always use static string literals as translation keys.** Our i18n scripts (`pnpm i18n:report`) rely on static analysis to detect unused and missing keys. Dynamic keys cannot be analyzed and will be flagged as errors.
527+
528+
**Bad:**
529+
530+
```vue
531+
<!-- Template literal -->
532+
<p>{{ $t(`package.tabs.${tab}`) }}</p>
533+
534+
<!-- Variable -->
535+
<p>{{ $t(myKey) }}</p>
536+
```
537+
538+
**Good:**
539+
540+
```typescript
541+
const { t } = useI18n()
542+
543+
const tabLabels = computed(() => ({
544+
readme: t('package.tabs.readme'),
545+
versions: t('package.tabs.versions'),
546+
}))
547+
```
548+
549+
```vue
550+
<p>{{ tabLabels[tab] }}</p>
551+
```
530552

531553
### Using i18n-ally (recommended)
532554

@@ -598,6 +620,40 @@ A coverage test in `test/unit/a11y-component-coverage.spec.ts` ensures all compo
598620
> [!IMPORTANT]
599621
> Just because axe-core doesn't find any obvious issues, it does not mean a component is accessible. Please do additional checks and use best practices.
600622
623+
### Lighthouse accessibility tests
624+
625+
In addition to component-level axe audits, the project runs full-page accessibility audits using [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci). These test the rendered pages in both light and dark mode against Lighthouse's accessibility category, requiring a perfect score.
626+
627+
#### How it works
628+
629+
1. The project is built in test mode (`pnpm build:test`), which activates server-side fixture mocking
630+
2. Lighthouse CI starts a preview server and audits three URLs: `/`, `/search?q=nuxt`, and `/package/nuxt`
631+
3. A Puppeteer setup script (`lighthouse-setup.cjs`) runs before each audit to set the color mode and intercept client-side API requests using the same fixtures as the E2E tests
632+
633+
#### Running locally
634+
635+
```bash
636+
# Build + run both light and dark audits
637+
pnpm test:a11y
638+
639+
# Or against an existing test build
640+
pnpm test:a11y:prebuilt
641+
642+
# Or run a single color mode manually
643+
pnpm build:test
644+
LIGHTHOUSE_COLOR_MODE=dark ./scripts/lighthouse-a11y.sh
645+
```
646+
647+
This requires Chrome or Chromium to be installed. The script will auto-detect common installation paths. Results are printed to the terminal and saved in `.lighthouseci/`.
648+
649+
#### Configuration
650+
651+
| File | Purpose |
652+
| ---------------------------- | --------------------------------------------------------- |
653+
| `.lighthouserc.cjs` | Lighthouse CI config (URLs, assertions, Chrome path) |
654+
| `lighthouse-setup.cjs` | Puppeteer script for color mode + client-side API mocking |
655+
| `scripts/lighthouse-a11y.sh` | Shell wrapper that runs the audit for a given color mode |
656+
601657
### End to end tests
602658

603659
Write end-to-end tests using Playwright:
@@ -619,10 +675,12 @@ E2E tests use a fixture system to mock external API requests, ensuring tests are
619675
- Serves pre-recorded fixture data from `test/fixtures/`
620676
- Enabled via `NUXT_TEST_FIXTURES=true` or Nuxt test mode
621677

622-
**Client-side mocking** (`test/e2e/test-utils.ts`):
678+
**Client-side mocking** (`test/fixtures/mock-routes.cjs`):
623679

624-
- Uses Playwright's route interception to mock browser requests
625-
- All test files import from `./test-utils` instead of `@nuxt/test-utils/playwright`
680+
- Shared URL matching and response generation logic used by both Playwright E2E tests and Lighthouse CI
681+
- Playwright tests (`test/e2e/test-utils.ts`) use this via `page.route()` interception
682+
- Lighthouse tests (`lighthouse-setup.cjs`) use this via Puppeteer request interception
683+
- All E2E test files import from `./test-utils` instead of `@nuxt/test-utils/playwright`
626684
- Throws a clear error if an unmocked external request is detected
627685

628686
#### Fixture files
@@ -670,7 +728,7 @@ URL: https://registry.npmjs.org/some-package
670728
You need to either:
671729

672730
1. Add a fixture file for that package/endpoint
673-
2. Update the mock handlers in `test/e2e/test-utils.ts` (client) or `modules/runtime/server/cache.ts` (server)
731+
2. Update the mock handlers in `test/fixtures/mock-routes.cjs` (client) or `modules/runtime/server/cache.ts` (server)
674732

675733
## Submitting changes
676734

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ npmx.dev supports npm permalinks &ndash; just replace `npmjs.com` with `npmx.dev
116116
| `npmjs.com/org/nuxt` | [`npmx.dev/org/nuxt`](https://npmx.dev/org/nuxt) |
117117

118118
> [!TIP]
119-
> Want automatic redirects? Try the [npmx-replace browser extension](https://github.com/tylersayshi/npmx-replace-extension).
119+
> Want automatic redirects? Try the [npmx-replace browser extension](https://github.com/tylersayshi/npmx-replace-extension) (Chrome only for now).
120120
121121
#### Not yet supported
122122

@@ -150,13 +150,14 @@ We welcome contributions &ndash; please do feel free to explore the project and
150150

151151
## Related projects
152152

153-
- [npmx-replace-extension](https://github.com/tylersayshi/npmx-replace-extension) &ndash; Browser extension to redirect npmjs.com to npmx.dev
153+
- [npmx-replace-extension](https://github.com/tylersayshi/npmx-replace-extension) &ndash; Browser extension to redirect npmjs.com to npmx.dev (Chrome only for now)
154154
- [JSR](https://jsr.io/) &ndash; The open-source package registry for modern JavaScript and TypeScript
155155
- [npm-userscript](https://github.com/bluwy/npm-userscript) &ndash; Browser userscript with various improvements and fixes for npmjs.com
156156
- [npm-alt](https://npm.willow.sh/) &ndash; An alternative npm package browser
157157
- [npkg.lorypelli.dev](https://npkg.lorypelli.dev/) &ndash; An alternative frontend to npm made with as little client-side JavaScript as possible
158158
- [vscode-npmx](https://github.com/npmx-dev/vscode-npmx) &ndash; VSCode extension for npmx
159159
- [nxjt](https://nxjt.netlify.app) &ndash; npmx Jump To: Quickly navigate to npmx common webpages.
160+
- [npmx-weekly](https://npmx-weekly.trueberryless.org/) &ndash; A weekly newsletter for the npmx ecosystem. Add your own content via suggestions in the weekly PR on [GitHub](https://github.com/trueberryless-org/npmx-weekly/pulls?q=is%3Aopen+is%3Apr+label%3A%22%F0%9F%95%94+weekly+post%22).
160161
- [npmx-digest](https://npmx-digest.trueberryless.org/) &ndash; An automated news aggregation website that summarizes npmx activity from GitHub and Bluesky every 8 hours.
161162

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

app/assets/main.css

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
--accent: var(--accent-color, oklch(1 0 0));
2828
--accent-muted: var(--accent-color, oklch(0.922 0 0));
2929

30+
/* accent colors */
31+
--swatch-coral: oklch(0.704 0.177 14.75);
32+
--swatch-amber: oklch(0.828 0.165 84.429);
33+
--swatch-emerald: oklch(0.792 0.153 166.95);
34+
--swatch-sky: oklch(0.787 0.128 230.318);
35+
--swatch-violet: oklch(0.78 0.148 286.067);
36+
--swatch-magenta: oklch(0.78 0.15 330);
37+
3038
/* syntax highlighting colors */
3139
--syntax-fn: oklch(0.727 0.137 299.149);
3240
--syntax-str: oklch(0.829 0.088 252.458);
@@ -89,6 +97,14 @@
8997
--accent: var(--accent-color, oklch(0.145 0 0));
9098
--accent-muted: var(--accent-color, oklch(0.205 0 0));
9199

100+
/* accent colors */
101+
--swatch-coral: oklch(0.7 0.19 14.75);
102+
--swatch-amber: oklch(0.8 0.25 84.429);
103+
--swatch-emerald: oklch(0.7 0.17 166.95);
104+
--swatch-sky: oklch(0.7 0.15 230.318);
105+
--swatch-violet: oklch(0.7 0.17 286.067);
106+
--swatch-magenta: oklch(0.75 0.18 330);
107+
92108
--syntax-fn: oklch(0.502 0.188 294.988);
93109
--syntax-str: oklch(0.425 0.152 252);
94110
--syntax-kw: oklch(0.588 0.193 20.469);
@@ -155,12 +171,32 @@
155171
}
156172
}
157173

174+
/*
175+
* Forced Colors Mode (WHCM) Override for Icons
176+
*
177+
* By default, `forced-color-adjust: preserve-parent-color` (from UnoConfig) works fine
178+
* for most icons as they inherit the correct text color.
179+
*
180+
* However, if icons disappear in specific contexts (e.g., inside buttons with
181+
* complex backgrounds or transparent states), uncomment the following block
182+
* to enforce visibility using `CanvasText`.
183+
*/
184+
/*
185+
@media (forced-colors: active) {
186+
[class^='i-'],
187+
[class*=' i-'] {
188+
forced-color-adjust: none !important;
189+
color: CanvasText !important;
190+
}
191+
}
192+
*/
193+
158194
html {
195+
@apply scroll-pt-20;
159196
-webkit-font-smoothing: antialiased;
160197
-moz-osx-font-smoothing: grayscale;
161198
text-rendering: optimizeLegibility;
162199
/* Offset for fixed header - otherwise anchor headers are cutted */
163-
scroll-padding-top: 5rem;
164200
scrollbar-gutter: stable;
165201
}
166202

@@ -200,11 +236,6 @@ dd {
200236
margin: 0;
201237
}
202238

203-
/* Reset button styles */
204-
button {
205-
cursor: pointer;
206-
}
207-
208239
/* Selection */
209240
::selection {
210241
background-color: var(--fg-muted);

0 commit comments

Comments
 (0)