content,internal: fix anchor target links for constants and variables

This change adds content to anchor links for package scoped
constants and variables and scroll padding to code blocks to
fix the issue where items selected from jump to identifier or
navigated to directly by page URL would appear off-screen.

Fixes golang/go#38575

Change-Id: I19a197be46b7e5f444e03e2a0a03146bf92cc953
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/283955
Trust: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/content/static/css/stylesheet.css b/content/static/css/stylesheet.css
index d3cf587..8c15678 100644
--- a/content/static/css/stylesheet.css
+++ b/content/static/css/stylesheet.css
@@ -1307,6 +1307,14 @@
   padding-top: 1.5rem;
   text-align: right;
 }
+.Documentation-declaration pre {
+  scroll-padding-top: calc(var(--header-height) + 3.75rem);
+}
+@media only screen and (min-width: 52rem) {
+  .Documentation-declaration pre {
+    scroll-padding-top: calc(var(--header-height) + 0.75rem);
+  }
+}
 .Documentation-declaration + .Documentation-declaration {
   margin-top: 0.625rem;
 }
diff --git a/internal/godoc/dochtml/internal/render/linkify.go b/internal/godoc/dochtml/internal/render/linkify.go
index 8701aa6..64afdcb 100644
--- a/internal/godoc/dochtml/internal/render/linkify.go
+++ b/internal/godoc/dochtml/internal/render/linkify.go
@@ -462,6 +462,7 @@
 	// Emit anchor IDs and data-kind attributes for each relevant line.
 	var htmls []safehtml.HTML
 	for line, iks := range anchorLines {
+		inAnchor := false
 		for _, ik := range iks {
 			// Attributes for types and functions are handled in the template
 			// that generates the full documentation HTML.
@@ -474,13 +475,17 @@
 				continue
 			}
 			htmls = append(htmls, ExecuteToHTML(anchorTemplate, ik))
+			inAnchor = true
 		}
 		htmls = append(htmls, htmlLines[line]...)
+		if inAnchor {
+			htmls = append(htmls, template.MustParseAndExecuteToHTML("</span>"))
+		}
 	}
 	return safehtml.HTMLConcat(htmls...)
 }
 
-var anchorTemplate = template.Must(template.New("anchor").Parse(`<span id="{{.ID}}" data-kind="{{.Kind}}"></span>`))
+var anchorTemplate = template.Must(template.New("anchor").Parse(`<span id="{{.ID}}" data-kind="{{.Kind}}">`))
 
 // declVisitor is an ast.Visitor that trims
 // large string literals and composite literals.
diff --git a/internal/godoc/dochtml/internal/render/linkify_test.go b/internal/godoc/dochtml/internal/render/linkify_test.go
index f2f4911..18cdd41 100644
--- a/internal/godoc/dochtml/internal/render/linkify_test.go
+++ b/internal/godoc/dochtml/internal/render/linkify_test.go
@@ -185,27 +185,27 @@
 			name:   "const",
 			symbol: "Nanosecond",
 			want: `const (
-<span id="Nanosecond" data-kind="constant"></span>	Nanosecond  <a href="#Duration">Duration</a> = 1
-<span id="Microsecond" data-kind="constant"></span>	Microsecond          = 1000 * <a href="#Nanosecond">Nanosecond</a>
-<span id="Millisecond" data-kind="constant"></span>	Millisecond          = 1000 * <a href="#Microsecond">Microsecond</a> <span class="comment">// comment</span>
-<span id="Second" data-kind="constant"></span>	Second               = 1000 * <a href="#Millisecond">Millisecond</a> <span class="comment">/* multi
+<span id="Nanosecond" data-kind="constant">	Nanosecond  <a href="#Duration">Duration</a> = 1
+</span><span id="Microsecond" data-kind="constant">	Microsecond          = 1000 * <a href="#Nanosecond">Nanosecond</a>
+</span><span id="Millisecond" data-kind="constant">	Millisecond          = 1000 * <a href="#Microsecond">Microsecond</a> <span class="comment">// comment</span>
+</span><span id="Second" data-kind="constant">	Second               = 1000 * <a href="#Millisecond">Millisecond</a> <span class="comment">/* multi
 	line
-	comment */</span>
-<span id="Minute" data-kind="constant"></span>	Minute = 60 * <a href="#Second">Second</a>
-<span id="Hour" data-kind="constant"></span>	Hour   = 60 * <a href="#Minute">Minute</a>
-)`,
+	comment */</span></span>
+<span id="Minute" data-kind="constant">	Minute = 60 * <a href="#Second">Second</a>
+</span><span id="Hour" data-kind="constant">	Hour   = 60 * <a href="#Minute">Minute</a>
+</span>)`,
 		},
 		{
 			name:   "var",
 			symbol: "UTC",
-			want:   `<span id="UTC" data-kind="variable"></span>var UTC *<a href="#Location">Location</a> = &amp;utcLoc`,
+			want:   `<span id="UTC" data-kind="variable">var UTC *<a href="#Location">Location</a> = &amp;utcLoc</span>`,
 		},
 		{
 			name:   "type",
 			symbol: "Ticker",
 			want: `type Ticker struct {
-<span id="Ticker.C" data-kind="field"></span>	C &lt;-chan <a href="#Time">Time</a> <span class="comment">// The channel on which the ticks are delivered.</span>
-	<span class="comment">// contains filtered or unexported fields</span>
+<span id="Ticker.C" data-kind="field">	C &lt;-chan <a href="#Time">Time</a> <span class="comment">// The channel on which the ticks are delivered.</span>
+</span>	<span class="comment">// contains filtered or unexported fields</span>
 
 }`,
 		},
@@ -223,8 +223,8 @@
 			name:   "interface",
 			symbol: "Iface",
 			want: `type Iface interface {
-<span id="Iface.M" data-kind="method"></span>	<span class="comment">// Method comment.</span>
-	M()
+<span id="Iface.M" data-kind="method">	<span class="comment">// Method comment.</span>
+</span>	M()
 
 	<span class="comment">// contains filtered or unexported methods</span>
 
@@ -234,11 +234,11 @@
 			name:   "long literal",
 			symbol: "TooLongLiteral",
 			want: `type TooLongLiteral struct {
-<span id="TooLongLiteral.Name" data-kind="field"></span>	<span class="comment">// The name.</span>
-	Name <a href="/builtin#string">string</a>
+<span id="TooLongLiteral.Name" data-kind="field">	<span class="comment">// The name.</span>
+</span>	Name <a href="/builtin#string">string</a>
 
-<span id="TooLongLiteral.Labels" data-kind="field"></span>	<span class="comment">// The labels.</span>
-	Labels <a href="/builtin#int">int</a> &#34;&#34; <span class="comment">/* 137 byte string literal not displayed */</span>
+<span id="TooLongLiteral.Labels" data-kind="field">	<span class="comment">// The labels.</span>
+</span>	Labels <a href="/builtin#int">int</a> &#34;&#34; <span class="comment">/* 137 byte string literal not displayed */</span>
 
 	<span class="comment">// contains filtered or unexported fields</span>