diff options
| author | Robert Griesemer <gri@golang.org> | 2009-10-01 14:08:00 -0700 |
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2009-10-01 14:08:00 -0700 |
| commit | 2402780f5fd37ffc355df81c539bdd09a526c3f9 (patch) | |
| tree | d788feee5c1fcfcf09d0ae99aef491b1270b5c04 /src/cmd/godoc/godoc.go | |
| parent | 28438e3dce3cdf3dab6f6e2be3f0a7e842d22593 (diff) | |
| download | golang-2402780f5fd37ffc355df81c539bdd09a526c3f9.tar.gz | |
Factored out boilerplate from all html docs in doc directory:
- the first HTML comment in those files is extracted as page
title when serving them
- lib/godoc.html is top-level template for all pages served
- experimented a bit with package documentation layout
(feedback welcome)
- various related cleanups
TODO:
- The / page (doc/root.html) content repeats links that are
in the navigation bar. It needs to be cleaned up.
R=rsc
DELTA=826 (86 added, 692 deleted, 48 changed)
OCL=35230
CL=35245
Diffstat (limited to 'src/cmd/godoc/godoc.go')
| -rw-r--r-- | src/cmd/godoc/godoc.go | 117 |
1 files changed, 75 insertions, 42 deletions
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 5164c39c2..1de4765a7 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -50,10 +50,7 @@ import ( ) -const ( - Pkg = "/pkg/"; // name for auto-generated package documentation tree - Spec = "/doc/go_spec.html"; -) +const Pkg = "/pkg/"; // name for auto-generated package documentation tree type delayTime struct { @@ -186,7 +183,7 @@ type parseErrors struct { func parse(path string, mode uint) (*ast.File, *parseErrors) { src, err := io.ReadFile(path); if err != nil { - log.Stderrf("ReadFile %s: %v", path, err); + log.Stderrf("%v", err); errs := []parseError{parseError{nil, 0, err.String()}}; return nil, &parseErrors{path, errs, nil}; } @@ -349,16 +346,16 @@ func readTemplates() { func servePage(c *http.Conn, title, content interface{}) { type Data struct { title interface{}; - header interface{}; timestamp string; content interface{}; } - var d Data; - d.title = title; - d.header = title; - d.timestamp = time.SecondsToLocalTime(syncTime.get()).String(); - d.content = content; + d := Data{ + title: title, + timestamp: time.SecondsToLocalTime(syncTime.get()).String(), + content: content, + }; + if err := godocHtml.Execute(&d, c); err != nil { log.Stderrf("godocHtml.Execute: %s", err); } @@ -374,18 +371,57 @@ func serveText(c *http.Conn, text []byte) { // ---------------------------------------------------------------------------- // Files +var ( + tagBegin = strings.Bytes("<!--"); + tagEnd = strings.Bytes("-->"); +) + +// commentText returns the text of the first HTML comment in src. +func commentText(src []byte) (text string) { + i := bytes.Index(src, tagBegin); + j := bytes.Index(src, tagEnd); + if i >= 0 && j >= i+len(tagBegin) { + text = string(bytes.TrimSpace(src[i+len(tagBegin) : j])); + } + return; +} + + +func serveHtmlDoc(c *http.Conn, r *http.Request, filename string) { + // get HTML body contents + path := pathutil.Join(goroot, filename); + src, err := io.ReadFile(path); + if err != nil { + log.Stderrf("%v", err); + http.NotFound(c, r); + return; + } + + // if it's the language spec, add tags to EBNF productions + if strings.HasSuffix(path, "go_spec.html") { + var buf bytes.Buffer; + linkify(&buf, src); + src = buf.Bytes(); + } + + title := commentText(src); + servePage(c, title, src); +} + + func serveParseErrors(c *http.Conn, errors *parseErrors) { // format errors var buf bytes.Buffer; if err := parseerrorHtml.Execute(errors, &buf); err != nil { log.Stderrf("parseerrorHtml.Execute: %s", err); } - servePage(c, errors.filename + " - Parse Errors", buf.Bytes()); + servePage(c, "Parse errors in source file " + errors.filename, buf.Bytes()); } -func serveGoSource(c *http.Conn, name string) { - prog, errors := parse(name, parser.ParseComments); +func serveGoSource(c *http.Conn, filename string) { + path := pathutil.Join(goroot, filename); + prog, errors := parse(path, parser.ParseComments); if errors != nil { serveParseErrors(c, errors); return; @@ -396,43 +432,35 @@ func serveGoSource(c *http.Conn, name string) { writeNode(&buf, prog, true); fmt.Fprintln(&buf, "</pre>"); - servePage(c, name + " - Go source", buf.Bytes()); -} - - -func serveGoSpec(c *http.Conn, r *http.Request) { - src, err := io.ReadFile(pathutil.Join(goroot, Spec)); - if err != nil { - http.NotFound(c, r); - return; - } - linkify(c, src); + servePage(c, "Source file " + filename, buf.Bytes()); } var fileServer = http.FileServer(".", ""); -func serveFile(c *http.Conn, req *http.Request) { +func serveFile(c *http.Conn, r *http.Request) { + path := r.Url.Path; + // pick off special cases and hand the rest to the standard file server - switch { - case req.Url.Path == "/": - // serve landing page. - // TODO: hide page from ordinary file serving. - // writing doc/index.html will take care of that. - http.ServeFile(c, req, "doc/root.html"); + switch ext := pathutil.Ext(path); { + case path == "/": + serveHtmlDoc(c, r, "doc/root.html"); - case req.Url.Path == "/doc/root.html": + case r.Url.Path == "/doc/root.html": // hide landing page from its real name - // TODO why - there is no reason for this (remove eventually) - http.NotFound(c, req); + http.NotFound(c, r); + + case ext == ".html": + serveHtmlDoc(c, r, path); - case pathutil.Ext(req.Url.Path) == ".go": - serveGoSource(c, req.Url.Path[1 : len(req.Url.Path)]); // strip leading '/' from name + case ext == ".go": + serveGoSource(c, path); default: - // TODO not good enough - don't want to download files - // want to see them - fileServer.ServeHTTP(c, req); + // TODO: + // - need to decide what to serve and what not to serve + // - don't want to download files, want to see them + fileServer.ServeHTTP(c, r); } } @@ -496,6 +524,7 @@ func getPageInfo(path string) PageInfo { // get package AST pkg, err := parser.ParsePackage(dirname, filter, parser.ParseComments); if err != nil { + // TODO: parse errors should be shown instead of an empty directory log.Stderr(err); } @@ -548,7 +577,12 @@ func servePkg(c *http.Conn, r *http.Request) { if path == "" { path = "."; // don't display an empty path } - servePage(c, path + " - Go package documentation", buf.Bytes()); + title := "Directory " + path; + if info.PDoc != nil { + title = "Package " + info.PDoc.PackageName; + } + + servePage(c, title, buf.Bytes()); } @@ -665,7 +699,6 @@ func main() { handler = loggingHandler(handler); } - http.Handle(Spec, http.HandlerFunc(serveGoSpec)); http.Handle(Pkg, http.HandlerFunc(servePkg)); if *syncCmd != "" { http.Handle("/debug/sync", http.HandlerFunc(dosync)); |
