summaryrefslogtreecommitdiff
path: root/internal/showcase
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-09 00:04:21 +0300
committerPaul Buetow <paul@buetow.org>2025-07-09 00:04:21 +0300
commitad18b17927c76f052d64313466dc7c117ff7719d (patch)
treee43f3e8ecd694763fed1178702598e4a483d5d38 /internal/showcase
parent6a2c0dc0dc81fcf22c513c5bc54b614ce5fb02f6 (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>
Diffstat (limited to 'internal/showcase')
-rw-r--r--internal/showcase/images.go11
-rw-r--r--internal/showcase/metadata.go34
-rw-r--r--internal/showcase/showcase.go5
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{
`!\[([^\]]*)\]\(([^)]+)\)`, // ![alt](url)
- `<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 ![alt](url)
} 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")