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>
This commit is contained in:
David Benjamin 2015-10-18 01:08:11 -04:00 committed by Adam Langley
parent 5ef619ef2a
commit dfa9c4a074

View File

@ -42,6 +42,8 @@ type HeaderFile struct {
// is a separate paragraph.
Preamble []string
Sections []HeaderSection
// AllDecls maps all decls to their URL fragments.
AllDecls map[string]string
}
type HeaderSection struct {
@ -283,6 +285,7 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
header := &HeaderFile{
Name: filepath.Base(path),
AllDecls: make(map[string]string),
}
for i, line := range lines {
@ -391,6 +394,8 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) {
// 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 @@ func firstSentence(paragraphs []string) string {
return s
}
func markupPipeWords(s string) template.HTML {
func markupPipeWords(allDecls map[string]string, s string) template.HTML {
ret := ""
for {
@ -442,7 +447,14 @@ func markupPipeWords(s string) template.HTML {
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 @@ again:
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 newlinesToBR(html template.HTML) template.HTML {
}
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 @@ func generate(outPath string, config *Config) (map[string]string, error) {
{{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 @@ func generate(outPath string, config *Config) (map[string]string, error) {
}
headerDescriptions := make(map[string]string)
var headers []*HeaderFile
for _, section := range config.Sections {
for _, headerPath := range section.Headers {
@ -552,6 +568,15 @@ func generate(outPath string, config *Config) (map[string]string, error) {
return nil, errors.New("while parsing " + headerPath + ": " + err.Error())
}
headerDescriptions[header.Name] = firstSentence(header.Preamble)
headers = append(headers, header)
for name, anchor := range header.AllDecls {
allDecls[name] = fmt.Sprintf("%s#%s", header.Name+".html", anchor)
}
}
}
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 {
@ -562,7 +587,6 @@ func generate(outPath string, config *Config) (map[string]string, error) {
return nil, err
}
}
}
return headerDescriptions, nil
}