@@ -163,9 +163,26 @@ private static bool IsGitHubUrl(string? url)
163163 . Concat ( links . Where ( l => ! NotRepositoryKeys . Any ( k => l . Key . Contains ( k , StringComparison . OrdinalIgnoreCase ) ) )
164164 . Select ( l => l . Value ) ) ;
165165
166- return candidates . Select ( RepositoryRoot ) . FirstOrDefault ( url => url != null ) ;
166+ return candidates . Select ( RepositoryRoot ) . FirstOrDefault ( url => url != null )
167+ ?? RepositoryFromDescription ( info ) ;
167168 }
168169
170+ private static string ? RepositoryFromDescription ( PyPIPackageInfo info )
171+ {
172+ if ( string . IsNullOrEmpty ( info . Description ) || string . IsNullOrEmpty ( info . Name ) )
173+ return null ;
174+
175+ var name = NormalizeName ( info . Name ) ;
176+ return System . Text . RegularExpressions . Regex . Matches ( info . Description ,
177+ @"https?://(?:www\.)?github\.com/[\w.-]+/[\w.-]+" ,
178+ System . Text . RegularExpressions . RegexOptions . IgnoreCase )
179+ . Select ( m => RepositoryRoot ( m . Value . TrimEnd ( '.' ) ) )
180+ . FirstOrDefault ( url => url != null && NormalizeName ( url [ ( url . LastIndexOf ( '/' ) + 1 ) .. ] ) == name ) ;
181+ }
182+
183+ private static string NormalizeName ( string name ) =>
184+ System . Text . RegularExpressions . Regex . Replace ( name , @"[-_.]+" , "-" ) . ToLowerInvariant ( ) ;
185+
169186 // https://github.com/{owner}/{repo} of a GitHub link (issues, a changelog file, releases), keeping a
170187 // /tree/{ref}/{folder} part that names the package folder of a monorepo; null for any other link
171188 private static string ? RepositoryRoot ( string ? url )
@@ -245,6 +262,9 @@ private class PyPIPackageInfo
245262
246263 [ JsonPropertyName ( "project_urls" ) ]
247264 public Dictionary < string , string > ? ProjectUrls { get ; set ; }
265+
266+ [ JsonPropertyName ( "description" ) ]
267+ public string ? Description { get ; set ; }
248268 }
249269
250270 private class PyPIReleaseFile
0 commit comments