Add conflict resolution diff UI and app branding

This commit is contained in:
2026-05-13 16:25:28 -04:00
parent 780ff3a02c
commit d359baa010
83 changed files with 4523 additions and 3735 deletions

View File

@@ -53,7 +53,16 @@ func NewRenderer() *Renderer {
}
func (r *Renderer) Render(content []byte) (Result, error) {
title := extractTitle(string(content))
title, titleFromHeading := extractTitle(string(content), "")
return r.renderWithTitle(content, title, titleFromHeading)
}
func (r *Renderer) RenderPath(content []byte, path string) (Result, error) {
title, titleFromHeading := extractTitle(string(content), path)
return r.renderWithTitle(content, title, titleFromHeading)
}
func (r *Renderer) renderWithTitle(content []byte, title string, titleFromHeading bool) (Result, error) {
tags := extractTags(string(content))
prepared := preprocess(string(content))
@@ -62,7 +71,10 @@ func (r *Renderer) Render(content []byte) (Result, error) {
return Result{}, fmt.Errorf("render markdown: %w", err)
}
html := firstH1Pattern.ReplaceAllString(output.String(), "")
html := output.String()
if titleFromHeading {
html = firstH1Pattern.ReplaceAllString(html, "")
}
return Result{
HTML: template.HTML(html),
@@ -123,13 +135,14 @@ func normalizeAdmonition(line string) string {
}
}
func extractTitle(content string) string {
func extractTitle(content string, path string) (string, bool) {
for _, line := range strings.Split(content, "\n") {
if strings.HasPrefix(line, "# ") {
return strings.TrimSpace(strings.TrimPrefix(line, "# "))
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "# ") {
return strings.TrimSpace(strings.TrimPrefix(trimmed, "# ")), true
}
}
return "Untitled"
return titleFromPath(path), false
}
func extractTags(content string) []string {
@@ -169,3 +182,35 @@ func slugify(value string) string {
}
return strings.Trim(builder.String(), "-")
}
func titleFromPath(path string) string {
path = strings.Trim(path, "/")
path = strings.TrimSuffix(path, ".md")
if path == "" {
return "Home"
}
base := path
if strings.HasSuffix(base, "/index") {
base = strings.TrimSuffix(base, "/index")
}
if base == "index" {
return "Home"
}
if idx := strings.LastIndex(base, "/"); idx >= 0 {
base = base[idx+1:]
}
base = strings.ReplaceAll(base, "-", " ")
base = strings.ReplaceAll(base, "_", " ")
parts := strings.Fields(base)
for i, part := range parts {
if part == strings.ToUpper(part) {
continue
}
parts[i] = strings.ToUpper(part[:1]) + strings.ToLower(part[1:])
}
if len(parts) == 0 {
return "Home"
}
return strings.Join(parts, " ")
}

View File

@@ -20,4 +20,34 @@ func TestRenderRewritesWikiLinksAndTags(t *testing.T) {
if len(result.Tags) != 2 || result.Tags[0] != "alpha" || result.Tags[1] != "beta" {
t.Fatalf("unexpected tags: %#v", result.Tags)
}
if strings.Contains(string(result.HTML), "<h1") {
t.Fatalf("expected first h1 to be removed from body html, got %s", result.HTML)
}
}
func TestRenderPathFallsBackToCleanedFileName(t *testing.T) {
renderer := NewRenderer()
result, err := renderer.RenderPath([]byte("Body only\n"), "guide/api-reference.md")
if err != nil {
t.Fatalf("RenderPath() error = %v", err)
}
if result.Title != "Api Reference" {
t.Fatalf("Title = %q, want Api Reference", result.Title)
}
}
func TestRenderPathUsesFolderNameForIndexFiles(t *testing.T) {
renderer := NewRenderer()
result, err := renderer.RenderPath([]byte("Body only\n"), "guide/index.md")
if err != nil {
t.Fatalf("RenderPath() error = %v", err)
}
if result.Title != "Guide" {
t.Fatalf("Title = %q, want Guide", result.Title)
}
}