Linkify pipe words. This required switching anchors from <a name> to id attributes, which also works. HTML gets unhappy when you nest <a> tags inside each other and tagging the elements is somewhat tidier. Change-Id: I64094d35a0e820e37be9e5dc8db013a50774190f Reviewed-on: https://boringssl-review.googlesource.com/6314 Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/util/doc.go b/util/doc.go index 48d65eb..ce7a3e8 100644 --- a/util/doc.go +++ b/util/doc.go
@@ -42,6 +42,8 @@ // is a separate paragraph. Preamble []string Sections []HeaderSection + // AllDecls maps all decls to their URL fragments. + AllDecls map[string]string } type HeaderSection struct { @@ -282,7 +284,8 @@ lines = lines[2:] header := &HeaderFile{ - Name: filepath.Base(path), + Name: filepath.Base(path), + AllDecls: make(map[string]string), } for i, line := range lines { @@ -391,6 +394,8 @@ // duplicate table-of-contents entries. allAnchors[anchor] = struct{}{} + header.AllDecls[name] = anchor + section.Decls = append(section.Decls, HeaderDecl{ Comment: comment, Name: name, @@ -426,7 +431,7 @@ return s } -func markupPipeWords(s string) template.HTML { +func markupPipeWords(allDecls map[string]string, s string) template.HTML { ret := "" for { @@ -442,7 +447,14 @@ j := strings.Index(s, " ") if i > 0 && (j == -1 || j > i) { ret += "<tt>" + anchor, isLink := allDecls[s[:i]] + if isLink { + ret += fmt.Sprintf("<a href=\"%s\">", template.HTMLEscapeString(anchor)) + } ret += s[:i] + if isLink { + ret += "</a>" + } ret += "</tt>" s = s[i+1:] } else { @@ -460,6 +472,11 @@ if end > 0 { end += start w := strings.ToLower(string(s[start:end])) + // The first word was already marked up as an HTML tag. Don't + // mark it up further. + if strings.ContainsRune(w, '<') { + return s + } if w == "a" || w == "an" { start = end + 1 goto again @@ -480,10 +497,12 @@ } func generate(outPath string, config *Config) (map[string]string, error) { + allDecls := make(map[string]string) + headerTmpl := template.New("headerTmpl") headerTmpl.Funcs(template.FuncMap{ "firstSentence": firstSentence, - "markupPipeWords": markupPipeWords, + "markupPipeWords": func(s string) template.HTML { return markupPipeWords(allDecls, s) }, "markupFirstWord": markupFirstWord, "newlinesToBR": newlinesToBR, }) @@ -514,23 +533,19 @@ {{range .Sections}} {{if not .IsPrivate}} - <div class="section"> + <div class="section" {{if .Anchor}}id="{{.Anchor}}"{{end}}> {{if .Preamble}} <div class="sectionpreamble"> - <a{{if .Anchor}} name="{{.Anchor}}"{{end}}> {{range .Preamble}}<p>{{. | html | markupPipeWords}}</p>{{end}} - </a> </div> {{end}} {{range .Decls}} - <div class="decl"> - <a{{if .Anchor}} name="{{.Anchor}}"{{end}}> + <div class="decl" {{if .Anchor}}id="{{.Anchor}}"{{end}}> {{range .Comment}} <p>{{. | html | markupPipeWords | newlinesToBR | markupFirstWord}}</p> {{end}} <pre>{{.Decl}}</pre> - </a> </div> {{end}} </div> @@ -544,6 +559,7 @@ } headerDescriptions := make(map[string]string) + var headers []*HeaderFile for _, section := range config.Sections { for _, headerPath := range section.Headers { @@ -552,15 +568,23 @@ return nil, errors.New("while parsing " + headerPath + ": " + err.Error()) } headerDescriptions[header.Name] = firstSentence(header.Preamble) - filename := filepath.Join(outPath, header.Name+".html") - file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) - if err != nil { - panic(err) + headers = append(headers, header) + + for name, anchor := range header.AllDecls { + allDecls[name] = fmt.Sprintf("%s#%s", header.Name+".html", anchor) } - defer file.Close() - if err := headerTmpl.Execute(file, header); err != nil { - return nil, err - } + } + } + + for _, header := range headers { + filename := filepath.Join(outPath, header.Name+".html") + file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + panic(err) + } + defer file.Close() + if err := headerTmpl.Execute(file, header); err != nil { + return nil, err } }