diff --git a/apps/web/src/services/ai/__tests__/icon-resolver.test.ts b/apps/web/src/services/ai/__tests__/icon-resolver.test.ts index 4a59a1140..2ab128aff 100644 --- a/apps/web/src/services/ai/__tests__/icon-resolver.test.ts +++ b/apps/web/src/services/ai/__tests__/icon-resolver.test.ts @@ -166,6 +166,12 @@ describe('applyIconPathResolution — opt-in marker gate', () => { ['Dismiss Icon', /x/], ['Cancel Icon', /x/], ['Remove Icon', /x/], + // `image` must NOT be in the noise word list — "Image Icon" is the + // standard lucide:image lookup and the user almost certainly means + // a picture icon, not "no signal". (`Image SVG` alone has no icon + // marker word so it bypasses the resolver entirely — that's correct + // because the path could be a real SVG file ref.) + ['Image Icon', /image/], ])('resolves multi-word path name "%s" to %s', (name, expectedIconId) => { const node = makePath({ name }); applyIconPathResolution(node); diff --git a/apps/web/src/services/ai/icon-resolver.ts b/apps/web/src/services/ai/icon-resolver.ts index 3b73af9dc..3f5c2c742 100644 --- a/apps/web/src/services/ai/icon-resolver.ts +++ b/apps/web/src/services/ai/icon-resolver.ts @@ -68,7 +68,11 @@ const ICON_NOISE_WORDS = new Set([ 'fill', 'svg', 'graphic', - 'image', + // Note: `image` is INTENTIONALLY not a noise word. It's a real lucide + // icon key, and "Image Icon" / "Image SVG" should resolve to lucide:image + // — not collapse to empty after stripping. Multi-word name patterns like + // "Image Placeholder Path" still resolve via the prefix fallback (`image` + // covers >= 50% of `imageplaceholder`). ]); function tokenizeName(name: string): string[] {