diff options
| author | Paul Buetow <paul@buetow.org> | 2025-07-09 00:04:21 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-07-09 00:04:21 +0300 |
| commit | ad18b17927c76f052d64313466dc7c117ff7719d (patch) | |
| tree | e43f3e8ecd694763fed1178702598e4a483d5d38 | |
| parent | 6a2c0dc0dc81fcf22c513c5bc54b614ce5fb02f6 (diff) | |
feat: add SVG image support and experimental project detection
- Fix image extraction regex to handle unquoted HTML img src attributes
- Add detection of version tags and experimental status for projects
- Display "Experimental (no releases yet)" for projects without tags
- Successfully extracts SVG images from projects like ior
๐ค Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
| -rw-r--r-- | internal/showcase/images.go | 11 | ||||
| -rw-r--r-- | internal/showcase/metadata.go | 34 | ||||
| -rw-r--r-- | internal/showcase/showcase.go | 5 |
3 files changed, 45 insertions, 5 deletions
diff --git a/internal/showcase/images.go b/internal/showcase/images.go index 0fa37f7..66372cb 100644 --- a/internal/showcase/images.go +++ b/internal/showcase/images.go @@ -125,7 +125,8 @@ func extractImageReferences(content string) []string { // Regex patterns for markdown images patterns := []string{ `!\[([^\]]*)\]\(([^)]+)\)`, //  - `<img[^>]+src=["']([^"']+)["'][^>]*>`, // <img src="url"> + `<img[^>]+src=["']([^"']+)["'][^>]*>`, // <img src="url"> with quotes + `<img[^>]+src=([^\s>]+)[^>]*>`, // <img src=url> without quotes `!\[([^\]]*)\]\[([^\]]+)\]`, // ![alt][ref] `\[([^\]]+)\]:\s*(.+?)(?:\s+"[^"]+")?\s*$`, // [ref]: url "title" } @@ -133,7 +134,7 @@ func extractImageReferences(content string) []string { fmt.Printf("DEBUG: Content length: %d bytes\n", len(content)) // Extract from markdown image syntax - for i, pattern := range patterns[:2] { // First two patterns have URLs in different positions + for i, pattern := range patterns[:3] { // First three patterns have URLs in different positions re := regexp.MustCompile(pattern) matches := re.FindAllStringSubmatch(content, -1) fmt.Printf("DEBUG: Pattern %d (%s) found %d matches\n", i, pattern, len(matches)) @@ -143,7 +144,7 @@ func extractImageReferences(content string) []string { if pattern == patterns[0] { url = match[2] // For  } else { - url = match[1] // For <img src="url"> + url = match[1] // For <img src="url"> (both with and without quotes) } // Clean and validate URL @@ -182,7 +183,7 @@ func extractImageReferences(content string) []string { } // Handle reference-style images - refPattern := regexp.MustCompile(patterns[3]) + refPattern := regexp.MustCompile(patterns[4]) refMatches := refPattern.FindAllStringSubmatch(content, -1) refs := make(map[string]string) for _, match := range refMatches { @@ -190,7 +191,7 @@ func extractImageReferences(content string) []string { } // Find reference-style image uses - refUsePattern := regexp.MustCompile(patterns[2]) + refUsePattern := regexp.MustCompile(patterns[3]) refUseMatches := refUsePattern.FindAllStringSubmatch(content, -1) for _, match := range refUseMatches { ref := match[2] diff --git a/internal/showcase/metadata.go b/internal/showcase/metadata.go index 13caf9f..9627910 100644 --- a/internal/showcase/metadata.go +++ b/internal/showcase/metadata.go @@ -28,6 +28,8 @@ type RepoMetadata struct { LastCommitDate string License string AvgCommitAge float64 // Average age of last 42 commits in days + LatestTag string // Latest version tag (empty if no tags) + HasReleases bool // Whether the project has any releases/tags } // extractRepoMetadata extracts metadata from a repository @@ -86,6 +88,14 @@ func extractRepoMetadata(repoPath string) (*RepoMetadata, error) { } metadata.AvgCommitAge = avgAge + // Get latest tag and check for releases + latestTag, hasReleases, err := getLatestTag(repoPath) + if err != nil { + fmt.Printf("Warning: Failed to get latest tag: %v\n", err) + } + metadata.LatestTag = latestTag + metadata.HasReleases = hasReleases + return metadata, nil } @@ -268,4 +278,28 @@ func getAverageCommitAge(repoPath string, commitCount int) (float64, error) { } return totalAge / float64(validCommits), nil +} + +// getLatestTag returns the latest git tag and whether the repo has any releases +func getLatestTag(repoPath string) (string, bool, error) { + // First try to get tags sorted by version + cmd := exec.Command("git", "-C", repoPath, "tag", "-l", "--sort=-version:refname") + output, err := cmd.Output() + if err != nil { + // Fallback to describe + cmd = exec.Command("git", "-C", repoPath, "describe", "--tags", "--abbrev=0") + output, err = cmd.Output() + if err != nil { + // No tags at all + return "", false, nil + } + } + + tags := strings.Split(strings.TrimSpace(string(output)), "\n") + if len(tags) == 0 || tags[0] == "" { + return "", false, nil + } + + // Return the latest tag + return tags[0], true, nil }
\ No newline at end of file diff --git a/internal/showcase/showcase.go b/internal/showcase/showcase.go index 0bce7ee..8f8592d 100644 --- a/internal/showcase/showcase.go +++ b/internal/showcase/showcase.go @@ -435,6 +435,11 @@ func (g *Generator) formatGemtext(summaries []ProjectSummary) string { builder.WriteString(fmt.Sprintf("* ๐ฅ Recent Activity: %.1f days (avg. age of last 42 commits)\n", summary.Metadata.AvgCommitAge)) builder.WriteString(fmt.Sprintf("* โ๏ธ License: %s\n", summary.Metadata.License)) + // Add experimental status if no releases + if !summary.Metadata.HasReleases { + builder.WriteString("* ๐งช Status: Experimental (no releases yet)\n") + } + // Add AI-Assisted notice if detected if summary.AIAssisted { builder.WriteString("* ๐ค AI-Assisted: This project was partially created with the help of generative AI\n") |
