From 5f84338225da7a8946b78e238717ca9055255ece Mon Sep 17 00:00:00 2001 From: Felix Schneider <99918022+trueberryless@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:59:42 +0200 Subject: [PATCH 1/4] fix(i18n): localize size increase/decrease percentage (#2828) Co-authored-by: CodeRabbit <132028505+coderabbitai@users.noreply.github.com> Co-authored-by: Willow (GHOST) <47755378+ghostdevv@users.noreply.github.com> --- app/components/Package/SizeDecrease.vue | 5 +++-- app/components/Package/SizeIncrease.vue | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/components/Package/SizeDecrease.vue b/app/components/Package/SizeDecrease.vue index 7872286046..fa730b6cd5 100644 --- a/app/components/Package/SizeDecrease.vue +++ b/app/components/Package/SizeDecrease.vue @@ -7,8 +7,9 @@ const props = defineProps<{ const bytesFormatter = useBytesFormatter() const numberFormatter = useNumberFormatter() +const percentFormatter = useNumberFormatter({ style: 'percent' }) -const sizePercent = computed(() => Math.round(Math.abs(props.diff.sizeRatio) * 100)) +const sizePercent = computed(() => percentFormatter.value.format(Math.abs(props.diff.sizeRatio))) const sizeDecreaseAbs = computed(() => Math.abs(props.diff.sizeIncrease)) const depDecreaseAbs = computed(() => Math.abs(props.diff.depDiff)) @@ -33,7 +34,7 @@ const depDecreaseAbs = computed(() => Math.abs(props.diff.depDiff))

{{ sizePercent }} Math.round(props.diff.sizeRatio * 100)) +const sizePercent = computed(() => percentFormatter.value.format(Math.abs(props.diff.sizeRatio))) Date: Mon, 1 Jun 2026 15:01:24 +0100 Subject: [PATCH 2/4] chore: minor ui improvements (#2834) --- app/components/AppHeader.vue | 2 +- app/components/Noodle/Pride1/Logo.vue | 2 +- app/pages/package-timeline/[[org]]/[packageName].vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue index e90464ca5b..32fc2fb91d 100644 --- a/app/components/AppHeader.vue +++ b/app/components/AppHeader.vue @@ -258,7 +258,7 @@ useShortcuts({

+
Date: Tue, 2 Jun 2026 10:14:07 +0200 Subject: [PATCH 3/4] fix: update colors when prefers-color-scheme changes (#2839) --- app/composables/useColors.ts | 21 ++++- test/unit/app/composables/use-colors.spec.ts | 83 +++++++++++++++++++- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/app/composables/useColors.ts b/app/composables/useColors.ts index 7a5248627f..87bbb64c5d 100644 --- a/app/composables/useColors.ts +++ b/app/composables/useColors.ts @@ -1,5 +1,18 @@ -import { computed, shallowRef, type ComputedRef, type Ref, type ShallowRef, unref } from 'vue' -import { useMutationObserver, useResizeObserver, useSupported } from '@vueuse/core' +import { + computed, + shallowRef, + type ComputedRef, + type Ref, + type ShallowRef, + unref, + watch, +} from 'vue' +import { + useMutationObserver, + useResizeObserver, + useSupported, + usePreferredDark, +} from '@vueuse/core' type CssVariableSource = HTMLElement | null | undefined | Ref @@ -36,6 +49,8 @@ export function useColors( options: { watchHtmlAttributes?: boolean; watchResize?: boolean } = {}, ): { colors: ComputedRef> } { const recomputeToken = shallowRef(0) + const isPreferredDark = usePreferredDark() + const invalidateColors = () => { recomputeToken.value += 1 } @@ -44,6 +59,8 @@ export function useColors( () => typeof window !== 'undefined' && typeof document !== 'undefined', ) + watch(isPreferredDark, invalidateColors) + const colors = computed>(() => { void recomputeToken.value const resolvedElement = resolveElement(element) diff --git a/test/unit/app/composables/use-colors.spec.ts b/test/unit/app/composables/use-colors.spec.ts index 6d8369a6c1..4ad3594446 100644 --- a/test/unit/app/composables/use-colors.spec.ts +++ b/test/unit/app/composables/use-colors.spec.ts @@ -1,12 +1,18 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { computed, shallowRef } from 'vue' +import { computed, nextTick, shallowRef, ref, type Ref } from 'vue' import { useColors } from '~/composables/useColors' const useSupportedMock = vi.hoisted(() => vi.fn()) const useMutationObserverMock = vi.hoisted(() => vi.fn()) const useResizeObserverMock = vi.hoisted(() => vi.fn()) +const vueUseMockState = vi.hoisted(() => ({ + preferredDark: undefined as unknown as Ref, +})) + vi.mock('@vueuse/core', () => { + vueUseMockState.preferredDark = ref(false) + return { useSupported: (callback: () => boolean) => { useSupportedMock(callback) @@ -14,12 +20,14 @@ vi.mock('@vueuse/core', () => { }, useMutationObserver: useMutationObserverMock, useResizeObserver: useResizeObserverMock, + usePreferredDark: () => vueUseMockState.preferredDark, } }) describe('useColors', () => { beforeEach(() => { vi.clearAllMocks() + vueUseMockState.preferredDark.value = false }) afterEach(() => { @@ -57,4 +65,77 @@ describe('useColors', () => { const { colors } = useColors(elementReference) expect(colors.value).toEqual({}) }) + + it('recomputes colors when preferred dark mode changes', async () => { + const styleValues = { + accent: '#FF0000', + } + + vi.stubGlobal('window', {}) + vi.stubGlobal('document', { + documentElement: {}, + }) + + vi.stubGlobal('getComputedStyle', () => ({ + getPropertyValue: (variableName: string) => { + if (variableName === '--accent') { + return styleValues.accent + } + + return '' + }, + })) + + const elementReference = shallowRef({} as HTMLElement) + const { colors } = useColors(elementReference) + expect(colors.value.accent).toBe('#FF0000') + styleValues.accent = '#00FF00' + vueUseMockState.preferredDark.value = true + await nextTick() + + expect(colors.value.accent).toBe('#00FF00') + }) + + it('attaches an html mutation observer when enabled', () => { + vi.stubGlobal('window', {}) + vi.stubGlobal('document', { + documentElement: {}, + }) + const elementReference = shallowRef(null) + useColors(elementReference, { + watchHtmlAttributes: true, + }) + expect(useMutationObserverMock).toHaveBeenCalledTimes(1) + expect(useMutationObserverMock).toHaveBeenCalledWith( + document.documentElement, + expect.any(Function), + { + attributes: true, + attributeFilter: ['class', 'style', 'data-theme', 'data-bg-theme'], + }, + ) + }) + + it('falls back to document element when no element is provided', () => { + vi.stubGlobal('window', {}) + vi.stubGlobal('document', { + documentElement: {}, + }) + vi.stubGlobal('getComputedStyle', (element: HTMLElement) => { + expect(element).toBe(document.documentElement) + + return { + getPropertyValue: (variableName: string) => { + if (variableName === '--accent') { + return 'red' + } + + return '' + }, + } + }) + const elementReference = shallowRef(null) + const { colors } = useColors(elementReference) + expect(colors.value.accent).toBe('red') + }) }) From 4aed48bbedf27958a0c383cf9229e9c08934ddc7 Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 2 Jun 2026 16:21:39 +0100 Subject: [PATCH 4/4] chore(deps): update module-replacements (#2838) --- package.json | 2 +- pnpm-lock.yaml | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 8216391118..21e41ec52c 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "gray-matter": "4.0.3", "ipaddr.js": "2.3.0", "marked": "18.0.0", - "module-replacements": "3.0.0-beta.7", + "module-replacements": "3.0.0-beta.8", "nuxt": "4.4.5", "nuxt-og-image": "^6.4.3", "ofetch": "1.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3e926aaa14..1d666694a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -190,8 +190,8 @@ importers: specifier: 18.0.0 version: 18.0.0 module-replacements: - specifier: 3.0.0-beta.7 - version: 3.0.0-beta.7 + specifier: 3.0.0-beta.8 + version: 3.0.0-beta.8 nuxt: specifier: 4.4.5 version: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) @@ -415,7 +415,7 @@ importers: version: 12.8.0 docus: specifier: 5.9.0 - version: 5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@2.0.1-rc.20)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29) + version: 5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29) nuxt: specifier: 4.4.5 version: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) @@ -2269,7 +2269,7 @@ packages: resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} '@lunariajs/core@https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935': - resolution: {tarball: https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935} + resolution: {integrity: sha512-N0PDFIitA/Vzh5V6BtTacWU9jgSDJJtPLHamRLMU85mohmyuVW/pggHX8dzdV5ieqZeHEz8pDZSzH4I0hOYxOg==, tarball: https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935} version: 0.1.1 engines: {node: '>=18.17.0'} @@ -4941,7 +4941,7 @@ packages: resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@storybook-vue/nuxt@https://pkg.pr.new/@storybook-vue/nuxt@1021': - resolution: {tarball: https://pkg.pr.new/@storybook-vue/nuxt@1021} + resolution: {integrity: sha512-OmpGHtbapfpljOkFY8/g+9EkNa+SPcVAcqOiOPyP6upXMSpwNHHfEXFMBiFWqF7xru82zHg2kkfmWArVpVG7tg==, tarball: https://pkg.pr.new/@storybook-vue/nuxt@1021} version: 9.0.1 engines: {node: '>=20.19.0'} peerDependencies: @@ -8845,6 +8845,9 @@ packages: module-replacements@3.0.0-beta.7: resolution: {integrity: sha512-n1F9l3gF1wNh13xmnXS2JU7P9c3DlzCgVEyLKrVN0U37RwrXyYoePMMvYvs/6aUONAxbnscphzESZTCorXFh7Q==} + module-replacements@3.0.0-beta.8: + resolution: {integrity: sha512-sc8TepP9elxoOBXEpxmhPzKKjTjbswHVcmsKGbgvm3k6jZlLu/WMV/Lfmga6IGMgHU/V3WtY2s6VEgM4nTElUQ==} + motion-dom@12.40.0: resolution: {integrity: sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==} @@ -14511,11 +14514,11 @@ snapshots: - uploadthing - vue - '@nuxtjs/mcp-toolkit@0.13.4(h3@2.0.1-rc.20)(magicast@0.5.2)(zod@4.3.6)': + '@nuxtjs/mcp-toolkit@0.13.4(h3@1.15.11)(magicast@0.5.2)(zod@4.3.6)': dependencies: '@modelcontextprotocol/sdk': 1.29.0(zod@4.3.6) '@nuxt/kit': 4.4.6(magicast@0.5.2) - h3: 2.0.1-rc.20 + h3: 1.15.11 tinyglobby: 0.2.16 zod: 4.3.6 transitivePeerDependencies: @@ -18198,7 +18201,7 @@ snapshots: doctypes@1.1.0: {} - docus@5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@2.0.1-rc.20)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29): + docus@5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29): dependencies: '@ai-sdk/gateway': 3.0.101(zod@4.3.6) '@ai-sdk/mcp': 1.0.36(zod@4.3.6) @@ -18211,7 +18214,7 @@ snapshots: '@nuxt/kit': 4.4.6(magicast@0.5.2) '@nuxt/ui': 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.2)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29)(zod@4.3.6) '@nuxtjs/i18n': 10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.34) - '@nuxtjs/mcp-toolkit': 0.13.4(h3@2.0.1-rc.20)(magicast@0.5.2)(zod@4.3.6) + '@nuxtjs/mcp-toolkit': 0.13.4(h3@1.15.11)(magicast@0.5.2)(zod@4.3.6) '@nuxtjs/mdc': 0.21.1(magicast@0.5.2) '@nuxtjs/robots': 6.0.9(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) '@shikijs/core': 4.1.0 @@ -20531,6 +20534,8 @@ snapshots: module-replacements@3.0.0-beta.7: {} + module-replacements@3.0.0-beta.8: {} + motion-dom@12.40.0: dependencies: motion-utils: 12.39.0