]> Cypherpunks.ru repositories - gostls13.git/commitdiff
Factored out boilerplate from all html docs in doc directory:
authorRobert Griesemer <gri@golang.org>
Thu, 1 Oct 2009 21:08:00 +0000 (14:08 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 1 Oct 2009 21:08:00 +0000 (14:08 -0700)
- 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

doc/effective_go.html
doc/go_for_cpp_programmers.html
doc/go_lang_faq.html
doc/go_mem.html
doc/go_spec.html
doc/go_tutorial.head
doc/go_tutorial.html
lib/godoc/package.html
lib/godoc/package.txt
lib/godoc/parseerror.html
src/cmd/godoc/godoc.go

index e9a1e2581591c0c249e6d3a0c7d37cc6839b2473..d72525c999ccd3917156756b334804eda86a91e4 100644 (file)
@@ -1,64 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
+<!-- Effective Go -->
 
 <!-- interfaces; slices; embedding; value vs. pointer receivers; methods on anything; errors; testing -->
 
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>Effective Go</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-<style type="text/css">
-pre.bad {
-  background-color: #ffeeee;
-}
-</style>
-
-</head>
-
-
-<body>  <!-- onload="prettyPrint()" will color the programs -->
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList" style="clear:both">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="effective_go">Effective Go</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
-
 <h2 id="introduction">Introduction</h2>
 
 <p>
@@ -187,7 +130,7 @@ x&lt;&lt;8 + y&lt;&lt;16
 <h2>Commentary</h2>
 
 <p>
-Go provides C-style <code>/* */</code> block comments 
+Go provides C-style <code>/* */</code> block comments
 and C++-style <code>//</code> line comments.
 Line comments are the norm;
 block comments appear mostly as package comments and
@@ -752,7 +695,7 @@ The return or result "parameters" of a Go function can be given names and
 used as regular variables, just like the incoming parameters.
 When named, they are initialized to the zero for their type when
 the function begins; if the function executes a <code>return</code> statement
-with no arguments, the current values of the result parameters are 
+with no arguments, the current values of the result parameters are
 used as the returned values.
 </p>
 
@@ -938,7 +881,7 @@ must be initialized before use.
 A slice, for example, is a three-item descriptor
 containing a pointer to the data (inside an array), the length, and the
 capacity; until those items are initialized, the slice is <code>nil</code>.
-For slices, maps, and channels, 
+For slices, maps, and channels,
 <code>make</code> initializes the internal data structure and prepares
 the value for use.
 For instance,
@@ -1066,7 +1009,7 @@ header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n];
 Especially in libraries, functions tend to have multiple error modes.
 Instead of returning a boolean to signal success,
 return an <code>os.Error</code> that describes the failure.
-Even if there is only one failure mode now, 
+Even if there is only one failure mode now,
 there may be more later.
 </p>
 
@@ -1255,9 +1198,9 @@ This data-driven style dominates in the Go package tests.
 <p>
 The <code>reflect.DeepEqual</code> function tests
 whether two complex data structures have equal values.
-If a function returns a complex data structure, 
+If a function returns a complex data structure,
 <code>reflect.DeepEqual</code> combined with table-driven testing
-makes it easy to check that the return value is 
+makes it easy to check that the return value is
 exactly as expected.
 </p>
 
@@ -1337,7 +1280,3 @@ lets readers concentrate on big ones.
 </p>
 
 -->
-
-</div>
-</body>
-</html>
index 14ed14957c368bca381fd7258b82998bf4014a92..055242f7163be0304be6a765345490dad7a71735 100644 (file)
@@ -1,59 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-       Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-       Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-       Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-       Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>Go For C++ Programmers</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">Go For C++ Programmers</h1>
+<!-- Go For C++ Programmers -->
 
 <p>
 Go is a systems programming language intended as an alternative to C++.
@@ -72,11 +17,6 @@ For a detailed description of the Go language, see the
 <p>
 There is more <a href="./">documentation about go</a>.
 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
-
 <h2 id="Conceptual_Differences">Conceptual Differences</h2>
 
 <ul>
@@ -666,14 +606,3 @@ func f4(ch &lt;- chan cmd2) int {
   return &lt;- my_ch;
 }
 </pre>
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
index 142a224857e87accc761fbced58a5f0c5ea728a7..e40c3b036297e3e0708d310d8399c9108e4df84b 100644 (file)
@@ -1,54 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Programming Language Design FAQ</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Design_FAQ">The Go Programming Language Design FAQ</h1> 
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Programming Language Design FAQ -->
 
 <h2 id="origins">Origins</h2>
 
@@ -416,15 +366,3 @@ why no automatic numeric conversions?
 
 make vs new
 </pre>
-
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
index 9239e9871317bb81fd3a35090bcc286f7b586d4f..d2167a66a3610bddee9ce76a7b1d0d148926f910 100644 (file)
@@ -1,64 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-       Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-       Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-       Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-       Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Memory Model</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">The Go Memory Model</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Memory Model -->
 
 <h2>Introduction</h2>
 
index d49a4a075574478f2dc036ec1622f94076cb17d7..afb85de02b997ddb04243e2e7297af92a079bcd9 100644 (file)
@@ -1,64 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/transitional.dtd">
-<html>
-<head>
-
-<!--
-To convert <h2>Foo</h2> into <h2 id="Foo">Foo</h2>
-and convert §Foo into §<a href="#Foo">Foo</a>:
-
-        Edit ,s/<(h.)>(.*)(<\/h.>)/<\1 id="\2">\2\3/g
-        Edit ,x g/id="/ x/id="[^"]+"/ s/ /_/g
-        Edit ,s/§([^),.]+)/§<a href="#\1">\1<\/a>/g
-        Edit ,x/href="#[^"]+"/ s/ /_/g
--->
-
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <title>The Go Programming Language Specification</title>
-
-  <link rel="stylesheet" type="text/css" href="style.css">
-  <script type="text/javascript" src="godocs.js"></script>
-
-</head>
-
-<body>
-
-<div id="topnav">
-<table summary=""><tr>
-<td id="headerImage">
-<a href="./"><img src="./logo_blue.png" height="44" width="120" alt="Go Home Page" style="border:0" /></a>
-</td>
-<td id="headerDocSetTitle">The Go Programming Language</td>
-</tr>
-</table>
-</div>
-
-<div id="linkList" style="clear:both">
-  <ul>
-    <li class="navhead">Related Guides</li>
-    <li><a href="go_spec.html">Language Specification</a></li>
-    <li><a href="go_mem.html">Memory Model</a></li>
-    <li><a href="go_tutorial.html">Tutorial</a></li>
-    <li><a href="effective_go.html">Effective Go</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Other Resources</li>
-    <li><a href="go_faq.html">FAQ</a></li>
-    <li><a href="go_lang_faq.html">Language Design FAQ</a></li>
-    <li><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></li>
-    <li class="blank">&nbsp;</li>
-    <li class="navhead">Home</li>
-    <li><a href="/">Go documentation home</a></li>
-  </ul>
-</div>
-
-<div id="content">
-
-<h1 id="The_Go_Programming_Language_Specification">The Go Programming Language Specification</h1>
-
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- The Go Programming Language Specification -->
 
 <!--
 Todo
@@ -4613,14 +4553,3 @@ The following minimal alignment properties are guaranteed:
        <li><font color=red>Gccgo does not implement the blank identifier.</font></li>
        <li><font color=red>Method expressions are not implemented.</font></li>
 </ul>
-
-</div>
-
-<div id="footer">
-<p>Except as noted, this content is
-   licensed under <a href="http://creativecommons.org/licenses/by/3.0/">
-   Creative Commons Attribution 3.0</a>.
-</div>
-
-</body>
-</html>
index c6977bd9cfc9bd2675468ea40edaa27d384bcc62..a15e53683bfaa301ef77b15f325849373aadc1a3 100644 (file)
@@ -1,8 +1,3 @@
-<div id="content">
-<h1 id="Lets_Go">Let's Go</h1> 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- Let's Go -->
 
 <h2>Introduction</h2>
index 1029d744d8a3790a0062ce0d3a0af087bade83e3..755e43db818099853073c42780732a9154261666 100644 (file)
@@ -1,8 +1,4 @@
-<h1 id="Lets_Go">Let's Go</h1> 
-
-  <!-- The Table of Contents is automatically inserted in this <div>.
-       Do not delete this <div>. -->
-  <div id="nav"></div>
+<!-- Let's Go -->
 
 <h2>Introduction</h2>
 <p>
@@ -602,7 +598,7 @@ Finally we can run the program:
     % helloworld3
     hello, world
     can't open file; err=No such file or directory
-    % 
+    %
 
 </pre>
 <h2>Rotting cats</h2>
@@ -770,7 +766,7 @@ Here it is in action:
     abcdefghijklmnopqrstuvwxyz
     % echo abcdefghijklmnopqrstuvwxyz | ./cat --rot13
     nopqrstuvwxyzabcdefghijklm
-    % 
+    %
 </pre>
 <p>
 Fans of dependency injection may take cheer from how easily interfaces
@@ -1354,5 +1350,3 @@ at the end of main:
 There's a lot more to Go programming and concurrent programming in general but this
 quick tour should give you some of the basics.
 </table>
-</body>
-</html>
index 1b577229cab02fb290f7866e6956340e32eda0f0..b703b2e707cc7d9a81adf15b6f6ab7b2cc5a2aa7 100644 (file)
@@ -4,14 +4,8 @@
        license that can be found in the LICENSE file.
 -->
 
-{.section Dirs}
-       <h2>Subdirectories</h2>
-       {.repeated section @}
-               <a href="{Name|html}">{Name|html}</a><br />
-       {.end}
-{.end}
 {.section PDoc}
-       <h1>package {PackageName|html}</h1>
+       <!-- PackageName is printed as title by the top-level template -->
        <p><code>import "{ImportPath|html}"</code></p>
        {Doc|html-comment}
        {.section Filenames}
@@ -77,3 +71,9 @@
                {.end}
        {.end}
 {.end}
+{.section Dirs}
+       <h2>Subdirectories</h2>
+       {.repeated section @}
+               <a href="{Name|html}">{Name|html}</a><br />
+       {.end}
+{.end}
index 8d836ccd19154a3815a4b870734e02ced79a6222..d8c3c3121190ca46b82ccddc7c881d1528a0e231 100644 (file)
@@ -1,10 +1,3 @@
-{.section Dirs}
-SUBDIRECTORIES
-{.repeated section @}
-       {Name}
-{.end}
-
-{.end}
 {.section PDoc}
 PACKAGE
 
@@ -75,3 +68,11 @@ BUGS
 {.end}
 {.end}
 {.end}
+{.section Dirs}
+
+SUBDIRECTORIES
+
+{.repeated section @}
+       {Name}
+{.end}
+{.end}
index 35d95621edbeb106f22c0dacda64fb3ab43d3660..361cffe8c1f2a00da504a580443319bf9a44f8fa 100644 (file)
@@ -4,7 +4,7 @@
        license that can be found in the LICENSE file.
 -->
 
-<h1>Parse errors in {filename}</h1>
 <pre>
 {.repeated section list}
-{src}{.section msg}<b><font color=red>«{msg|html}»</font></b>{.end}{.end}</pre>
+{src}{.section msg}<b><font color=red>«{msg|html}»</font></b>{.end}{.end}
+</pre>
index 5164c39c2ddedeba37bddb08cb9f635af72c7817..1de4765a78ad5c0270035e67ae2b31e8078c6e29 100644 (file)
@@ -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));