internal/cmd/weave: keep track of minimum header depth

Allow for outlines that start at a header level greater than 1, by
keeping track of the minimum header level encountered in the table of
contents.

Change-Id: I779726531883ecae3f980eb47cefe886ffef8b4f
Reviewed-on: https://go-review.googlesource.com/c/example/+/703895
Reviewed-by: Alan Donovan <adonovan@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/cmd/weave/weave.go b/internal/cmd/weave/weave.go
index bca5c82..20d16ea 100644
--- a/internal/cmd/weave/weave.go
+++ b/internal/cmd/weave/weave.go
@@ -87,7 +87,19 @@
 	printf("<!-- Autogenerated by weave; DO NOT EDIT -->\n")
 
 	// Pass 1: extract table of contents.
-	var toc []string
+	type tocEntry struct {
+		depth  int
+		text   string
+		anchor string
+	}
+	var (
+		toc []tocEntry
+		// We indent toc items according to their header depth, so that nested
+		// headers result in nested lists. However, we want the lowest header depth
+		// to correspond to the root of the list. Otherwise, the entire list is
+		// indented, which turns it into a code block rather than an outline.
+		minTocDepth int
+	)
 	scanner := bufio.NewScanner(in)
 	for scanner.Scan() {
 		line := scanner.Text()
@@ -97,9 +109,13 @@
 		line = strings.TrimSpace(line)
 		if line == "%toc" {
 			toc = nil
+			minTocDepth = 0
 		} else if strings.HasPrefix(line, "# ") || strings.HasPrefix(line, "## ") {
 			words := strings.Fields(line)
 			depth := len(words[0])
+			if minTocDepth == 0 || depth < minTocDepth {
+				minTocDepth = depth
+			}
 			words = words[1:]
 			text := strings.Join(words, " ")
 			anchor := strings.Join(words, "-")
@@ -107,8 +123,7 @@
 			anchor = strings.ReplaceAll(anchor, "**", "")
 			anchor = strings.ReplaceAll(anchor, "`", "")
 			anchor = strings.ReplaceAll(anchor, "_", "")
-			line = fmt.Sprintf("%s1. [%s](#%s)", strings.Repeat("\t", depth-1), text, anchor)
-			toc = append(toc, line)
+			toc = append(toc, tocEntry{depth: depth, text: text, anchor: anchor})
 		}
 	}
 	if scanner.Err() != nil {
@@ -125,7 +140,7 @@
 		switch {
 		case strings.HasPrefix(line, "%toc"): // ToC
 			for _, h := range toc {
-				printf("%s\n", h)
+				printf("%s1. [%s](#%s)\n", strings.Repeat("\t", h.depth-minTocDepth), h.text, h.anchor)
 			}
 		case strings.HasPrefix(line, "%include"):
 			words := strings.Fields(line)