internal/gaby: fix and improve search results template

The template referred to non-existent fields. Fix those.

Also, add links to URLs.

Change-Id: I1537da2430ad6dcf1ad17d19a5a2ad046af22246
Reviewed-on: https://go-review.googlesource.com/c/oscar/+/609139
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
diff --git a/internal/gaby/search.go b/internal/gaby/search.go
index 5783ceb..c78dae9 100644
--- a/internal/gaby/search.go
+++ b/internal/gaby/search.go
@@ -10,6 +10,7 @@
 	"fmt"
 	"io"
 	"net/http"
+	"net/url"
 
 	"github.com/google/safehtml/template"
 	"golang.org/x/oscar/internal/llm"
@@ -38,6 +39,7 @@
 type searchResult struct {
 	Title   string
 	VResult storage.VectorResult
+	IDIsURL bool // VResult.ID can be parsed as a URL
 }
 
 func (g *Gaby) search(query string) ([]searchResult, error) {
@@ -52,7 +54,8 @@
 		if d, ok := g.docs.Get(r.ID); ok {
 			title = d.Title
 		}
-		srs = append(srs, searchResult{title, r})
+		_, err := url.Parse(r.ID)
+		srs = append(srs, searchResult{title, r, err == nil})
 	}
 	return srs, nil
 }
@@ -76,6 +79,8 @@
 <html>
   <head>
     <title>Oscar Search</title>
+    <!-- All links open in another tab. -->
+    <base target="_blank">
   </head>
   <body>
     <h1>Vector search</h1>
@@ -95,13 +100,19 @@
   </head>
   <body>
   <h1>Search results for "{{.Query}}"</h1>
-  {{with .Results}}
-	  {{range .Results}}
-	     <p>{{.Title}}: {{.Vresult.ID}} ({{.VResult.Score}})</p>
+  {{- with .Results -}}
+	  {{- range . }}
+	     <p>{{with .Title}}{{.}}: {{end -}}
+	    {{if .IDIsURL -}}
+	      {{with .VResult}}<a href="{{.ID}}">{{.ID}}</a>{{end -}}
+	    {{else -}}
+	      {{.VResult.ID}}
+	    {{end -}}
+	    {{" "}}({{.VResult.Score}})</p>
 	  {{end}}
-  {{else}}
+  {{- else -}}
      No results.
-  {{end}}
+  {{- end}}
   </body>
 </html>
 `))
diff --git a/internal/gaby/search_test.go b/internal/gaby/search_test.go
new file mode 100644
index 0000000..cf6b27a
--- /dev/null
+++ b/internal/gaby/search_test.go
@@ -0,0 +1,48 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"strings"
+	"testing"
+
+	"golang.org/x/oscar/internal/storage"
+)
+
+func TestSearchResultsHTML(t *testing.T) {
+	query := "some query"
+	searchResults := []searchResult{
+		{
+			Title: "t1",
+			VResult: storage.VectorResult{
+				ID:    "https://example.com/x",
+				Score: 0.987654321,
+			},
+			IDIsURL: true,
+		},
+		{
+			VResult: storage.VectorResult{
+				ID:    "https://example.com/y",
+				Score: 0.876,
+			},
+			IDIsURL: false,
+		},
+	}
+	gotb, err := searchResultsHTML(query, searchResults)
+	if err != nil {
+		t.Fatal(err)
+	}
+	wants := []string{query}
+	for _, sr := range searchResults {
+		wants = append(wants, sr.VResult.ID)
+	}
+	got := string(gotb)
+	t.Logf("%s", got)
+	for _, w := range wants {
+		if !strings.Contains(got, w) {
+			t.Errorf("did not find %q in HTML", w)
+		}
+	}
+}