feat: add README rendering and enhanced package metadata display
**Database Schema:** - Add npmReadme, npmKeywords, npmAuthor, npmMaintainers fields to Tool model **NPM Client:** - Add fetchLatestPackageWithMetadata() function to fetch README and top-level metadata - Export new PackageVersionWithReadme type **Sync Workers:** - Update keyword and changes sync to fetch and store README content - Store author, maintainers, and keywords from package.json **UI Components:** - Create Markdown component using react-markdown with GitHub Flavored Markdown - Add rehype-sanitize for security and remark-gfm for tables/strikethrough support **Tool Detail Page:** - Convert from createElement to JSX for better maintainability - Display README in a dedicated card with proper markdown rendering - Show NPM keywords, author, and maintainers in sidebar - Add ThemeToggle to header - Improve layout with better spacing and organization This brings the tool detail pages much closer to NPM's package pages, providing users with comprehensive information about each tool including the full README documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
506251bfa5
commit
32499bbc68
9 changed files with 1583 additions and 560 deletions
|
|
@ -22,6 +22,10 @@ model Tool {
|
|||
npmRepository Json? @map("npm_repository") @db.JsonB
|
||||
npmHomepage String? @map("npm_homepage") @db.Text
|
||||
npmLicense String? @map("npm_license") @db.VarChar(50)
|
||||
npmKeywords String[] @default([]) @map("npm_keywords") @db.Text
|
||||
npmReadme String? @map("npm_readme") @db.Text
|
||||
npmAuthor Json? @map("npm_author") @db.JsonB
|
||||
npmMaintainers Json? @map("npm_maintainers") @db.JsonB
|
||||
|
||||
// TPMJS Metadata (from package.json tpmjs field)
|
||||
category String @db.VarChar(50)
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@ export {
|
|||
export {
|
||||
fetchPackageMetadata,
|
||||
fetchLatestPackageVersion,
|
||||
fetchLatestPackageWithMetadata,
|
||||
fetchPackageTpmjsField,
|
||||
type PackageVersion,
|
||||
type PackageMetadata,
|
||||
type PackageVersionWithReadme,
|
||||
} from './package';
|
||||
|
||||
// Download statistics
|
||||
|
|
|
|||
|
|
@ -160,6 +160,48 @@ export async function fetchLatestPackageVersion(
|
|||
};
|
||||
}
|
||||
|
||||
export type PackageVersionWithReadme = PackageVersion & {
|
||||
readme?: string;
|
||||
topLevelKeywords?: string[];
|
||||
topLevelDescription?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the latest version of a package with additional top-level metadata
|
||||
* @param packageName - The name of the package
|
||||
* @returns The latest package version with README and top-level metadata, or null if not found
|
||||
*/
|
||||
export async function fetchLatestPackageWithMetadata(
|
||||
packageName: string
|
||||
): Promise<PackageVersionWithReadme | null> {
|
||||
const metadata = await fetchPackageMetadata(packageName);
|
||||
|
||||
if (!metadata) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const latestTag = metadata['dist-tags'].latest;
|
||||
if (!latestTag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const version = metadata.versions[latestTag];
|
||||
if (!version) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add publishedAt from metadata.time
|
||||
const publishedAt = metadata.time?.[latestTag];
|
||||
|
||||
return {
|
||||
...version,
|
||||
publishedAt,
|
||||
readme: metadata.readme,
|
||||
topLevelKeywords: metadata.keywords,
|
||||
topLevelDescription: metadata.description,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a package has a tpmjs field in its latest version
|
||||
* @param packageName - The name of the package
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue