Skip to content

Commit fcb9aaf

Browse files
Merge pull request #204 from community-scripts/fix/185
fix/185: normalize script matching to handle underscore vs hyphen differences
2 parents adccee0 + 266ff5a commit fcb9aaf

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

src/app/_components/DownloadedScriptsTab.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ export function DownloadedScriptsTab({ onInstallScript }: DownloadedScriptsTabPr
169169

170170
// Update scripts with download status and filter to only downloaded scripts
171171
const downloadedScripts = React.useMemo((): ScriptCardType[] => {
172+
// Helper to normalize identifiers so underscores vs hyphens don't break matches
173+
const normalizeId = (s?: string): string => (s ?? '')
174+
.toLowerCase()
175+
.replace(/\.(sh|bash|py|js|ts)$/g, '')
176+
.replace(/[^a-z0-9]+/g, '-')
177+
.replace(/^-+|-+$/g, '');
178+
172179
return combinedScripts
173180
.map(script => {
174181
if (!script?.name) {
@@ -178,9 +185,13 @@ export function DownloadedScriptsTab({ onInstallScript }: DownloadedScriptsTabPr
178185
// Check if there's a corresponding local script
179186
const hasLocalVersion = localScriptsData?.scripts?.some(local => {
180187
if (!local?.name) return false;
181-
const localName = local.name.replace(/\.sh$/, '');
182-
return localName.toLowerCase() === script.name.toLowerCase() ||
183-
localName.toLowerCase() === (script.slug ?? '').toLowerCase();
188+
const normalizedLocal = normalizeId(local.name);
189+
const matchesNameOrSlug = (
190+
normalizedLocal === normalizeId(script.name) ||
191+
normalizedLocal === normalizeId(script.slug)
192+
);
193+
const matchesInstallBasename = (script as any)?.install_basenames?.some((base: string) => normalizeId(base) === normalizedLocal) ?? false;
194+
return matchesNameOrSlug || matchesInstallBasename;
184195
}) ?? false;
185196

186197
return {

src/app/_components/ScriptsGrid.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ export function ScriptsGrid({ onInstallScript }: ScriptsGridProps) {
200200

201201
// Update scripts with download status
202202
const scriptsWithStatus = React.useMemo((): ScriptCardType[] => {
203+
// Helper to normalize identifiers for robust matching
204+
const normalizeId = (s?: string): string => (s ?? '')
205+
.toLowerCase()
206+
.replace(/\.(sh|bash|py|js|ts)$/g, '')
207+
.replace(/[^a-z0-9]+/g, '-')
208+
.replace(/^-+|-+$/g, '');
209+
203210
return combinedScripts.map(script => {
204211
if (!script?.name) {
205212
return script; // Return as-is if invalid
@@ -208,9 +215,13 @@ export function ScriptsGrid({ onInstallScript }: ScriptsGridProps) {
208215
// Check if there's a corresponding local script
209216
const hasLocalVersion = localScriptsData?.scripts?.some(local => {
210217
if (!local?.name) return false;
211-
const localName = local.name.replace(/\.sh$/, '');
212-
return localName.toLowerCase() === script.name.toLowerCase() ||
213-
localName.toLowerCase() === (script.slug ?? '').toLowerCase();
218+
const normalizedLocal = normalizeId(local.name);
219+
const matchesNameOrSlug = (
220+
normalizedLocal === normalizeId(script.name) ||
221+
normalizedLocal === normalizeId(script.slug)
222+
);
223+
const matchesInstallBasename = (script as any)?.install_basenames?.some((base: string) => normalizeId(base) === normalizedLocal) ?? false;
224+
return matchesNameOrSlug || matchesInstallBasename;
214225
}) ?? false;
215226

216227
return {

src/server/api/routers/scripts.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ export const scriptsRouter = createTRPCRouter({
177177
const firstInstallMethod = script?.install_methods?.[0];
178178
const os = firstInstallMethod?.resources?.os;
179179
const version = firstInstallMethod?.resources?.version;
180+
// Extract install basenames for robust local matching (e.g., execute.sh -> execute)
181+
const install_basenames = (script?.install_methods ?? [])
182+
.map(m => m?.script)
183+
.filter((p): p is string => typeof p === 'string')
184+
.map(p => {
185+
const parts = p.split('/');
186+
const file = parts[parts.length - 1] ?? '';
187+
return file.replace(/\.(sh|bash|py|js|ts)$/i, '');
188+
});
180189

181190
return {
182191
...card,
@@ -189,6 +198,7 @@ export const scriptsRouter = createTRPCRouter({
189198
version: version,
190199
// Add interface port
191200
interface_port: script?.interface_port,
201+
install_basenames,
192202
} as ScriptCard;
193203
});
194204

src/types/script.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ export interface ScriptCard {
6060
os?: string;
6161
version?: string;
6262
interface_port?: number | null;
63+
// Optional: basenames of install scripts (without extension)
64+
install_basenames?: string[];
6365
}
6466

6567
export interface GitHubFile {

0 commit comments

Comments
 (0)