diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-29 10:42:44 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-29 10:42:44 +0300 |
| commit | 4513ccec70871532b5b06aed3f9ed720abf613ed (patch) | |
| tree | 25affcce796b10407a7631b389ef291081195e8c | |
| parent | 78a1bada950fbdbbc9a3de1cf7bd9f87e7768d55 (diff) | |
refactor(showcase): extract summary and asset helpers (kq)
| -rw-r--r-- | internal/showcase/showcase.go | 79 | ||||
| -rw-r--r-- | internal/showcase/showcase_test.go | 112 |
2 files changed, 167 insertions, 24 deletions
diff --git a/internal/showcase/showcase.go b/internal/showcase/showcase.go index 936c9f4..e32d144 100644 --- a/internal/showcase/showcase.go +++ b/internal/showcase/showcase.go @@ -445,6 +445,54 @@ func (g *Generator) generateProjectSummary(repoName string, forceRegenerate bool // Continue anyway with partial metadata } + summary := g.resolveSummary( + repoName, + repoPath, + selectedTool, + readmeFile, + readmeContent, + readmeFound, + cachedSummary, + haveCachedSummary, + ) + + // Build URLs + codebergURL, githubURL, cgitURL := g.buildProjectLinks(repoName) + + images, codeSnippet, codeLanguage, err := g.collectAssets(repoName, repoPath, statsRepoPath, metadata) + if err != nil { + return nil, err + } + + projectSummary := &ProjectSummary{ + Name: repoName, + Summary: summary, + CodebergURL: codebergURL, + GitHubURL: githubURL, + CgitURL: cgitURL, + Metadata: metadata, + Images: images, + CodeSnippet: codeSnippet, + CodeLanguage: codeLanguage, + } + + // Save to cache + if err := g.saveToCache(cacheFile, projectSummary); err != nil { + fmt.Printf("Warning: Failed to save to cache: %v\n", err) + } else { + fmt.Printf("Summary cached at: %s\n", cacheFile) + } + + return projectSummary, nil +} + +func (g *Generator) resolveSummary( + repoName, repoPath, selectedTool, readmeFile string, + readmeContent []byte, + readmeFound bool, + cachedSummary string, + haveCachedSummary bool, +) string { // Get the summary - either from cache or by running AI tool var summary string if haveCachedSummary { @@ -459,21 +507,23 @@ func (g *Generator) generateProjectSummary(repoName string, forceRegenerate bool summary = fallbackSummary(repoName, readmeContent, readmeFound) } } + summary = extractUsefulSummary(summary, 2) if summary == "" { summary = fallbackSummary(repoName, readmeContent, readmeFound) } - summary = sanitizeSummaryForGemtext(summary) - // Build URLs - codebergURL, githubURL, cgitURL := g.buildProjectLinks(repoName) + return sanitizeSummaryForGemtext(summary) +} +func (g *Generator) collectAssets(repoName, repoPath, statsRepoPath string, metadata *RepoMetadata) ([]string, string, string, error) { // Always extract images from README (not cached) fmt.Printf("Extracting images from README...\n") showcaseDir, err := showcaseOutputDir() if err != nil { - return nil, err + return nil, "", "", err } + images, err := extractImagesFromRepo(repoPath, repoName, showcaseDir) if err != nil { fmt.Printf("Warning: Failed to extract images: %v\n", err) @@ -492,26 +542,7 @@ func (g *Generator) generateProjectSummary(repoName string, forceRegenerate bool } } - projectSummary := &ProjectSummary{ - Name: repoName, - Summary: summary, - CodebergURL: codebergURL, - GitHubURL: githubURL, - CgitURL: cgitURL, - Metadata: metadata, - Images: images, - CodeSnippet: codeSnippet, - CodeLanguage: codeLanguage, - } - - // Save to cache - if err := g.saveToCache(cacheFile, projectSummary); err != nil { - fmt.Printf("Warning: Failed to save to cache: %v\n", err) - } else { - fmt.Printf("Summary cached at: %s\n", cacheFile) - } - - return projectSummary, nil + return images, codeSnippet, codeLanguage, nil } // showcaseOutputDir returns the canonical directory where showcase output files diff --git a/internal/showcase/showcase_test.go b/internal/showcase/showcase_test.go index 6341e41..dac32b5 100644 --- a/internal/showcase/showcase_test.go +++ b/internal/showcase/showcase_test.go @@ -254,6 +254,118 @@ func TestFallbackSummary_SkipsHeadingOnlyParagraphs(t *testing.T) { } } +func TestResolveSummary_CachedSummaryFallsBackToReadmeWhenNoUsefulParagraph(t *testing.T) { + t.Parallel() + + g := &Generator{} + readmeContent := []byte("useful README summary paragraph") + + got := g.resolveSummary( + "repo", + t.TempDir(), + "opencode", + "README.md", + readmeContent, + true, + "* item one\n* item two", + true, + ) + + if got != "useful README summary paragraph" { + t.Fatalf("resolveSummary() = %q, want README fallback", got) + } +} + +func TestResolveSummary_NoCacheAndNoReadmeUsesGenericFallback(t *testing.T) { + t.Parallel() + + g := &Generator{} + + got := g.resolveSummary( + "repo", + t.TempDir(), + "opencode", + "", + nil, + false, + "", + false, + ) + + if got != "repo: source code repository." { + t.Fatalf("resolveSummary() = %q, want generic fallback", got) + } +} + +func TestCollectAssets_ReturnsImagesAndSkipsSnippetWithoutLanguages(t *testing.T) { + homeDir := t.TempDir() + t.Setenv("HOME", homeDir) + + repoName := "demo" + repoPath := filepath.Join(t.TempDir(), repoName) + if err := os.MkdirAll(repoPath, 0755); err != nil { + t.Fatalf("mkdir repo: %v", err) + } + + if err := os.WriteFile(filepath.Join(repoPath, "README.md"), []byte(""), 0644); err != nil { + t.Fatalf("write README.md: %v", err) + } + if err := os.WriteFile(filepath.Join(repoPath, "shot.png"), []byte("png"), 0644); err != nil { + t.Fatalf("write shot.png: %v", err) + } + + g := &Generator{} + images, snippet, language, err := g.collectAssets(repoName, repoPath, repoPath, nil) + if err != nil { + t.Fatalf("collectAssets() error = %v", err) + } + + if len(images) != 1 || images[0] != filepath.Join("showcase", repoName, "image-1.png") { + t.Fatalf("collectAssets() images = %#v", images) + } + if snippet != "" || language != "" { + t.Fatalf("collectAssets() snippet/language = %q/%q, want empty", snippet, language) + } + + copiedPath := filepath.Join(homeDir, "git", "foo.zone-content", "gemtext", "about", images[0]) + if _, err := os.Stat(copiedPath); err != nil { + t.Fatalf("expected copied image at %s: %v", copiedPath, err) + } +} + +func TestCollectAssets_ContinuesWhenSnippetExtractionFails(t *testing.T) { + homeDir := t.TempDir() + t.Setenv("HOME", homeDir) + + repoName := "demo" + repoPath := filepath.Join(t.TempDir(), repoName) + if err := os.MkdirAll(repoPath, 0755); err != nil { + t.Fatalf("mkdir repo: %v", err) + } + + if err := os.WriteFile(filepath.Join(repoPath, "README.md"), []byte(""), 0644); err != nil { + t.Fatalf("write README.md: %v", err) + } + + g := &Generator{} + metadata := &RepoMetadata{ + Languages: []LanguageStats{ + {Name: "Go", Lines: 10, Percentage: 100}, + }, + } + + images, snippet, language, err := g.collectAssets(repoName, repoPath, repoPath, metadata) + if err != nil { + t.Fatalf("collectAssets() error = %v", err) + } + if len(images) != 0 { + t.Fatalf("collectAssets() images = %#v, want no images", images) + } + if snippet != "" || language != "" { + t.Fatalf("collectAssets() snippet/language = %q/%q, want empty after extraction error", snippet, language) + } +} + func TestSelectSummaryTool_DefaultPrefersOpencode(t *testing.T) { t.Parallel() |
