Skip to content

Commit da1a640

Browse files
committed
feat: display platforms and compatibility on the package page
1 parent 088da82 commit da1a640

File tree

2 files changed

+75
-25
lines changed

2 files changed

+75
-25
lines changed

src/extension.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { exec } from 'node:child_process';
2-
import { workspace, commands, window, type ExtensionContext, QuickPickItemKind, env, Uri } from 'vscode';
2+
import { commands, env, type ExtensionContext, QuickPickItemKind, Uri, window, workspace } from 'vscode';
33

44
import { detectPackageManager } from './detectPackageManager';
55
import { DirectoryEntry } from './types';
66
import {
7+
deduplicateSearchTokens,
78
ENTRY_OPTION,
89
fetchData,
910
getCommandToRun,
11+
getCompatibilityList,
12+
getPlatformsList,
1013
KEYWORD_REGEX,
1114
numberFormatter,
15+
openListWithSearch,
1216
STRINGS,
1317
VALID_KEYWORDS_MAP,
1418
ValidKeyword
@@ -77,6 +81,9 @@ export async function activate(context: ExtensionContext) {
7781
]
7882
: [];
7983

84+
const platformsList = getPlatformsList(selectedEntry);
85+
const compatibilityList = getCompatibilityList(selectedEntry);
86+
8087
const possibleActions = [
8188
workspacePath && {
8289
label: ENTRY_OPTION.INSTALL,
@@ -106,6 +113,15 @@ export async function activate(context: ExtensionContext) {
106113
description: selectedEntry.github.license.name
107114
},
108115
{ label: ENTRY_OPTION.VIEW_BUNDLEPHOBIA },
116+
{ label: 'details', kind: QuickPickItemKind.Separator },
117+
{
118+
label: ENTRY_OPTION.PLATFORMS,
119+
description: platformsList.join(', ')
120+
},
121+
compatibilityList.length > 0 && {
122+
label: ENTRY_OPTION.COMPATIBILITY,
123+
description: compatibilityList.join(', ')
124+
},
109125
...examplesActions,
110126
{ label: 'copy data', kind: QuickPickItemKind.Separator },
111127
{ label: ENTRY_OPTION.COPY_NAME },
@@ -141,7 +157,9 @@ export async function activate(context: ExtensionContext) {
141157
break;
142158
}
143159
case ENTRY_OPTION.VISIT_HOMEPAGE: {
144-
env.openExternal(Uri.parse(selectedEntry.github.urls.homepage!));
160+
if (selectedEntry.github.urls.homepage) {
161+
env.openExternal(Uri.parse(selectedEntry.github.urls.homepage));
162+
}
145163
break;
146164
}
147165
case ENTRY_OPTION.VISIT_REPO: {
@@ -152,12 +170,22 @@ export async function activate(context: ExtensionContext) {
152170
env.openExternal(Uri.parse(`https://www.npmjs.com/package/${selectedEntry.npmPkg}`));
153171
break;
154172
}
173+
case ENTRY_OPTION.VIEW_LICENSE: {
174+
env.openExternal(Uri.parse(selectedEntry.github.license.url));
175+
break;
176+
}
155177
case ENTRY_OPTION.VIEW_BUNDLEPHOBIA: {
156178
env.openExternal(Uri.parse(`https://bundlephobia.com/package/${selectedEntry.npmPkg}`));
157179
break;
158180
}
159-
case ENTRY_OPTION.VIEW_LICENSE: {
160-
env.openExternal(Uri.parse(selectedEntry.github.license.url));
181+
case ENTRY_OPTION.PLATFORMS: {
182+
const searchValue = deduplicateSearchTokens(packagesPick.value, platformsList);
183+
await openListWithSearch(packagesPick, searchValue);
184+
break;
185+
}
186+
case ENTRY_OPTION.COMPATIBILITY: {
187+
const searchValue = deduplicateSearchTokens(packagesPick.value, compatibilityList);
188+
await openListWithSearch(packagesPick, searchValue);
161189
break;
162190
}
163191
case ENTRY_OPTION.COPY_NAME: {
@@ -176,14 +204,7 @@ export async function activate(context: ExtensionContext) {
176204
break;
177205
}
178206
case ENTRY_OPTION.GO_BACK: {
179-
packagesPick.placeholder = STRINGS.PLACEHOLDER_BUSY;
180-
packagesPick.busy = true;
181-
182-
packagesPick.show();
183-
packagesPick.items = await fetchData(packagesPick.value);
184-
185-
packagesPick.placeholder = STRINGS.PLACEHOLDER;
186-
packagesPick.busy = false;
207+
await openListWithSearch(packagesPick);
187208
break;
188209
}
189210
}

src/utils.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { window } from 'vscode';
1+
import { QuickPick, window } from 'vscode';
22

33
import { DirectoryEntry, PackageData } from './types';
44

@@ -17,7 +17,9 @@ export enum ENTRY_OPTION {
1717
COPY_NAME = 'Copy package name',
1818
COPY_REPO_URL = 'Copy GitHub repository URL',
1919
COPY_NPM_URL = 'Copy npm registry URL',
20-
GO_BACK = '$(newline) Go back to search'
20+
GO_BACK = '$(newline) Go back to search',
21+
PLATFORMS = 'Platforms',
22+
COMPATIBILITY = 'Compatibility'
2123
}
2224

2325
export enum STRINGS {
@@ -51,22 +53,12 @@ export const VALID_KEYWORDS_MAP = {
5153
export type ValidKeyword = keyof typeof VALID_KEYWORDS_MAP;
5254

5355
function getDetailLabel(item: PackageData) {
54-
const platforms = [
55-
item.android ? 'Android' : null,
56-
item.ios ? 'iOS' : null,
57-
item.macos ? 'macOS' : null,
58-
item.tvos ? 'tvOS' : null,
59-
item.visionos ? 'visionOS' : null,
60-
item.web ? 'Web' : null,
61-
item.windows ? 'Windows' : null
62-
].filter(Boolean);
63-
6456
return [
6557
`$(star) ${numberFormatter.format(item.github.stats.stars)}`,
6658
`$(gist-fork) ${numberFormatter.format(item.github.stats.forks)}`,
6759
item.npm?.downloads && `$(arrow-circle-down) ${numberFormatter.format(item.npm.downloads)}`,
6860
'•',
69-
platforms.join(', '),
61+
getPlatformsList(item).join(', '),
7062
(item.newArchitecture || item.expoGo || item.github.hasTypes) && '•',
7163
(item.newArchitecture || item.expoGo) && `$(verified) New Architecture`,
7264
item.github.hasTypes && `$(symbol-type-parameter) Types`
@@ -124,3 +116,40 @@ export async function fetchData(query?: string, keywords?: ValidKeyword[]): Prom
124116
return [];
125117
}
126118
}
119+
120+
export function getPlatformsList(item: PackageData): string[] {
121+
return [
122+
item.android ? 'Android' : null,
123+
item.ios ? 'iOS' : null,
124+
item.macos ? 'macOS' : null,
125+
item.tvos ? 'tvOS' : null,
126+
item.visionos ? 'visionOS' : null,
127+
item.web ? 'Web' : null,
128+
item.windows ? 'Windows' : null
129+
].filter((platform) => platform !== null);
130+
}
131+
132+
export function getCompatibilityList(item: PackageData): string[] {
133+
return [item.expoGo ? 'Expo Go' : null, item.fireos ? 'FireOS' : null].filter((entry) => entry !== null);
134+
}
135+
136+
export function formatAsSearchParams(list: string[]) {
137+
return list.map((entry) => `:${entry.replace(' ', '')}`);
138+
}
139+
140+
export function deduplicateSearchTokens(query: string, tokens: string[]) {
141+
return Array.from(new Set([...query.split(' '), ...formatAsSearchParams(tokens)])).join(' ');
142+
}
143+
144+
export async function openListWithSearch(packagesPick: QuickPick<DirectoryEntry>, query: string = packagesPick.value) {
145+
packagesPick.placeholder = STRINGS.PLACEHOLDER_BUSY;
146+
packagesPick.busy = true;
147+
148+
packagesPick.value = query;
149+
150+
packagesPick.show();
151+
packagesPick.items = await fetchData(query);
152+
153+
packagesPick.placeholder = STRINGS.PLACEHOLDER;
154+
packagesPick.busy = false;
155+
}

0 commit comments

Comments
 (0)