Skip to content

Commit 171d446

Browse files
gameromanautofix-ci[bot]ghostdevv
authored
feat: add WASM label (#2154)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Willow (GHOST) <git@willow.sh>
1 parent 49aba47 commit 171d446

File tree

10 files changed

+123
-29
lines changed

10 files changed

+123
-29
lines changed

app/components/Package/MetricsBadges.vue

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const hasCjs = computed(() => {
2626
return analysis.value.moduleFormat === 'cjs' || analysis.value.moduleFormat === 'dual'
2727
})
2828
29+
const isWasm = computed(() => {
30+
if (!analysis.value) return false
31+
return analysis.value.moduleFormat === 'wasm'
32+
})
33+
2934
// Types support
3035
const hasTypes = computed(() => {
3136
if (!analysis.value) return false
@@ -80,35 +85,45 @@ const typesHref = computed(() => {
8085
</TooltipApp>
8186
</li>
8287

83-
<!-- ESM badge (show with X if missing) -->
84-
<li class="contents">
85-
<TooltipApp
86-
:text="isLoading ? '' : hasEsm ? $t('package.metrics.esm') : $t('package.metrics.no_esm')"
87-
strategy="fixed"
88-
>
89-
<TagStatic
90-
tabindex="0"
91-
:variant="hasEsm && !isLoading ? 'default' : 'ghost'"
92-
:classicon="
93-
isLoading ? 'i-svg-spinners:ring-resize ' : hasEsm ? 'i-lucide:check' : 'i-lucide:x'
94-
"
95-
>
96-
ESM
97-
</TagStatic>
98-
</TooltipApp>
99-
</li>
88+
<template v-if="isWasm && !isLoading">
89+
<li class="contents">
90+
<TooltipApp :text="$t('package.metrics.wasm')" strategy="fixed">
91+
<TagStatic tabindex="0" variant="default">WASM</TagStatic>
92+
</TooltipApp>
93+
</li>
94+
</template>
10095

101-
<!-- CJS badge -->
102-
<li v-if="isLoading || hasCjs" class="contents">
103-
<TooltipApp :text="isLoading ? '' : $t('package.metrics.cjs')" strategy="fixed">
104-
<TagStatic
105-
tabindex="0"
106-
:variant="isLoading ? 'ghost' : 'default'"
107-
:classicon="isLoading ? 'i-svg-spinners:ring-resize ' : 'i-lucide:check'"
96+
<template v-else>
97+
<!-- ESM badge (show with X if missing) -->
98+
<li class="contents">
99+
<TooltipApp
100+
:text="isLoading ? '' : hasEsm ? $t('package.metrics.esm') : $t('package.metrics.no_esm')"
101+
strategy="fixed"
108102
>
109-
CJS
110-
</TagStatic>
111-
</TooltipApp>
112-
</li>
103+
<TagStatic
104+
tabindex="0"
105+
:variant="hasEsm && !isLoading ? 'default' : 'ghost'"
106+
:classicon="
107+
isLoading ? 'i-svg-spinners:ring-resize ' : hasEsm ? 'i-lucide:check' : 'i-lucide:x'
108+
"
109+
>
110+
ESM
111+
</TagStatic>
112+
</TooltipApp>
113+
</li>
114+
115+
<!-- CJS badge -->
116+
<li v-if="isLoading || hasCjs" class="contents">
117+
<TooltipApp :text="isLoading ? '' : $t('package.metrics.cjs')" strategy="fixed">
118+
<TagStatic
119+
tabindex="0"
120+
:variant="isLoading ? 'ghost' : 'default'"
121+
:classicon="isLoading ? 'i-svg-spinners:ring-resize ' : 'i-lucide:check'"
122+
>
123+
CJS
124+
</TagStatic>
125+
</TooltipApp>
126+
</li>
127+
</template>
113128
</ul>
114129
</template>

i18n/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@
533533
"esm": "ES Modules supported",
534534
"cjs": "CommonJS supported",
535535
"no_esm": "ES Modules unsupported",
536+
"wasm": "Has WebAssembly",
536537
"types_label": "Types",
537538
"types_included": "Types included",
538539
"types_available": "Types available via {package}",

i18n/schema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,9 @@
16031603
"no_esm": {
16041604
"type": "string"
16051605
},
1606+
"wasm": {
1607+
"type": "string"
1608+
},
16061609
"types_label": {
16071610
"type": "string"
16081611
},

shared/utils/package-analysis.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Package analysis utilities for detecting module format and TypeScript support
33
*/
44

5-
export type ModuleFormat = 'esm' | 'cjs' | 'dual' | 'unknown'
5+
export type ModuleFormat = 'esm' | 'cjs' | 'dual' | 'wasm' | 'unknown'
66

77
export type TypesStatus =
88
| { kind: 'included' }
@@ -88,6 +88,11 @@ export function detectModuleFormat(pkg: ExtendedPackageJson): ModuleFormat {
8888
return mainIsCJS ? 'dual' : 'esm'
8989
}
9090

91+
const mainIsWASM = pkg.main?.endsWith('.wasm')
92+
if (mainIsWASM) {
93+
return 'wasm'
94+
}
95+
9196
if (hasModule || isTypeModule) {
9297
return 'esm'
9398
}
File renamed without changes.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { afterEach, describe, expect, it, vi } from 'vitest'
2+
import { mockNuxtImport, mountSuspended } from '@nuxt/test-utils/runtime'
3+
import type { VueWrapper } from '@vue/test-utils'
4+
import { ref } from 'vue'
5+
import PackageMetricsBadges from '~/components/Package/MetricsBadges.vue'
6+
7+
const { mockUsePackageAnalysis } = vi.hoisted(() => ({
8+
mockUsePackageAnalysis: vi.fn(),
9+
}))
10+
11+
mockNuxtImport('usePackageAnalysis', () => mockUsePackageAnalysis)
12+
13+
describe('PackageMetricsBadges', () => {
14+
let wrapper: VueWrapper
15+
16+
afterEach(() => wrapper?.unmount())
17+
18+
it('renders the badges', async () => {
19+
mockUsePackageAnalysis.mockReturnValue({
20+
data: ref({ moduleFormat: 'dual', types: { kind: 'included' } }),
21+
status: ref('success'),
22+
})
23+
24+
wrapper = await mountSuspended(PackageMetricsBadges, {
25+
props: { packageName: 'ufo' },
26+
})
27+
28+
const text = wrapper.text()
29+
expect(text).toContain('Types')
30+
expect(text).toContain('ESM')
31+
expect(text).toContain('CJS')
32+
expect(text).not.toContain('WASM')
33+
})
34+
35+
it('renders the wasm label', async () => {
36+
mockUsePackageAnalysis.mockReturnValue({
37+
data: ref({ moduleFormat: 'wasm' }),
38+
status: ref('success'),
39+
})
40+
41+
wrapper = await mountSuspended(PackageMetricsBadges, {
42+
props: { packageName: 'swc-plugin-transform-webpack-context' },
43+
})
44+
45+
const text = wrapper.text()
46+
expect(text).toContain('WASM')
47+
expect(text).not.toContain('ESM')
48+
})
49+
50+
it('does not render the CJS label when no CJS', async () => {
51+
mockUsePackageAnalysis.mockReturnValue({
52+
data: ref({ moduleFormat: 'esm', types: { kind: 'included' } }),
53+
status: ref('success'),
54+
})
55+
56+
wrapper = await mountSuspended(PackageMetricsBadges, {
57+
props: { packageName: '@nuxt/kit' },
58+
})
59+
60+
const text = wrapper.text()
61+
expect(text).toContain('Types')
62+
expect(text).toContain('ESM')
63+
expect(text).not.toContain('CJS')
64+
expect(text).not.toContain('WASM')
65+
})
66+
})
File renamed without changes.
File renamed without changes.

test/nuxt/components/PackageWeeklyDownloadStats.spec.ts renamed to test/nuxt/components/Package/WeeklyDownloadStats.spec.ts

File renamed without changes.

test/unit/shared/utils/package-analysis.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ describe('detectModuleFormat', () => {
122122
}),
123123
).toBe('esm')
124124
})
125+
126+
it('detects WASM from main field', () => {
127+
expect(detectModuleFormat({ main: 'main.wasm' })).toBe('wasm')
128+
})
125129
})
126130

127131
describe('detectTypesStatus', () => {

0 commit comments

Comments
 (0)