Write documentation to docs.zip

This commit is contained in:
Trevor Slocum 2020-02-26 06:10:28 -08:00
parent 7f2dab8f89
commit d35eebc599
4 changed files with 92 additions and 43 deletions

View File

@ -1,4 +1,5 @@
0.1.6:
- Write documentation to docs.zip
- Create temporary directory when missing
0.1.5:

View File

@ -38,22 +38,10 @@ Packages are not downloaded/updated automatically.
### Usage examples
Generate documentation for `archive`, `net/http` and `gitlab.com/tslocum/cview` targeting `https://docs.rocketnine.space`:
Generate documentation for `archive`, `net/http` and `gitlab.com/tslocum/cview`:
```bash
godoc-static \
-base-path=/ \
-site-name="Rocket Nine Labs Documentation" \
-site-description="Welcome!" \
-destination=/home/user/sites/docs \
archive net/http gitlab.com/tslocum/cview
```
Targeting `https://rocketnine.space/docs/`:
```bash
godoc-static \
-base-path=/docs/ \
-site-name="Rocket Nine Labs Documentation" \
-site-description-file=/home/user/sitefiles/description.md \
-destination=/home/user/sites/docs \
@ -62,9 +50,6 @@ godoc-static \
### Options
#### -base-path
Site relative URL path with trailing slash.
#### -destination
Path to write site to.
@ -95,6 +80,9 @@ Site name.
#### -verbose
Enable verbose logging.
#### -zip
Site ZIP file name.
## Support
Please share issues/suggestions [here](https://gitlab.com/tslocum/godoc-static/issues).
Please share issues and suggestions [here](https://gitlab.com/tslocum/godoc-static/issues).

76
main.go
View File

@ -2,6 +2,7 @@
package main
import (
"archive/zip"
"bytes"
"errors"
"flag"
@ -27,18 +28,19 @@ import (
var (
listenAddress string
basePath string
siteName string
siteDescription string
siteDescriptionFile string
siteFooter string
siteFooterFile string
siteDestination string
siteZip string
linkIndex bool
excludePackages string
verbose bool
godoc *exec.Cmd
godoc *exec.Cmd
outZip *zip.Writer
)
func main() {
@ -46,13 +48,13 @@ func main() {
log.SetFlags(0)
flag.StringVar(&listenAddress, "listen-address", "localhost:9001", "address for godoc to listen on while scraping pages")
flag.StringVar(&basePath, "base-path", "/", "site relative URL path with trailing slash")
flag.StringVar(&siteName, "site-name", "Documentation", "site name")
flag.StringVar(&siteDescription, "site-description", "", "site description (markdown-enabled)")
flag.StringVar(&siteDescriptionFile, "site-description-file", "", "path to markdown file containing site description")
flag.StringVar(&siteFooter, "site-footer", "", "site footer (markdown-enabled)")
flag.StringVar(&siteFooterFile, "site-footer-file", "", "path to markdown file containing site footer")
flag.StringVar(&siteDestination, "destination", "", "path to write site to")
flag.StringVar(&siteDestination, "destination", "", "path to write site HTML")
flag.StringVar(&siteZip, "zip", "docs.zip", "name of site ZIP file (blank to disable)")
flag.BoolVar(&linkIndex, "link-index", false, "set link targets to index.html instead of folder")
flag.StringVar(&excludePackages, "exclude", "", "list of packages to exclude from index")
flag.BoolVar(&verbose, "verbose", false, "enable verbose logging")
@ -78,6 +80,28 @@ func getTmpDir() string {
return tmpDir
}
func writeFile(buf *bytes.Buffer, fileDir string, fileName string) error {
if outZip != nil {
fn := fileDir
if fn != "" {
fn += "/"
}
fn += fileName
outZipFile, err := outZip.Create(fn)
if err != nil {
return fmt.Errorf("failed to create zip file %s: %s", fn, err)
}
_, err = outZipFile.Write(buf.Bytes())
if err != nil {
return fmt.Errorf("failed to write zip file %s: %s", fn, err)
}
}
return ioutil.WriteFile(path.Join(siteDestination, fileDir, fileName), buf.Bytes(), 0755)
}
func run() error {
var buf bytes.Buffer
timeStarted := time.Now()
@ -138,10 +162,15 @@ func run() error {
siteFooter = buf.String()
}
if siteFooter != "" {
siteFooter += "<p>" + footerText + "</p>"
} else {
siteFooter = footerText
if siteZip != "" {
outZipFile, err := os.Create(filepath.Join(siteDestination, siteZip))
if err != nil {
return fmt.Errorf("failed to create zip file %s: %s", filepath.Join(siteDestination, siteZip), err)
}
defer outZipFile.Close()
outZip = zip.NewWriter(outZipFile)
defer outZip.Close()
}
if verbose {
@ -285,7 +314,7 @@ func run() error {
doc.Find("title").First().SetHtml(fmt.Sprintf("%s - %s", path.Base(pkg), siteName))
updatePage(doc, basePath, siteName)
updatePage(doc, relativeBasePath(pkg), siteName)
localPkgPath := path.Join(siteDestination, pkg)
@ -301,7 +330,7 @@ func run() error {
done <- fmt.Errorf("failed to render HTML: %s", err)
return
}
err = ioutil.WriteFile(path.Join(localPkgPath, "index.html"), buf.Bytes(), 0755)
err = writeFile(&buf, pkg, "index.html")
if err != nil {
done <- fmt.Errorf("failed to write docs for %s: %s", pkg, err)
return
@ -378,7 +407,7 @@ func run() error {
doc.Find("title").First().SetHtml(fmt.Sprintf("%s - %s", path.Base(pkg), siteName))
updatePage(doc, basePath, siteName)
updatePage(doc, relativeBasePath("src/"+pkg), siteName)
doc.Find(".layout").First().Find("a").Each(func(_ int, selection *goquery.Selection) {
href := selection.AttrOr("href", "")
@ -404,7 +433,7 @@ func run() error {
if !strings.HasSuffix(outFileName, ".html") {
outFileName += ".html"
}
err = ioutil.WriteFile(path.Join(pkgSrcPath, outFileName), buf.Bytes(), 0755)
err = writeFile(&buf, "src/"+pkg, outFileName)
if err != nil {
return fmt.Errorf("failed to write docs for %s: %s", pkg, err)
}
@ -427,17 +456,19 @@ func run() error {
return fmt.Errorf("failed to get syle.css: %s", err)
}
content, err := ioutil.ReadAll(res.Body)
buf.Reset()
_, err = buf.ReadFrom(res.Body)
res.Body.Close()
if err != nil {
return fmt.Errorf("failed to get style.css: %s", err)
}
content = append(content, []byte("\n"+additionalCSS+"\n")...)
buf.WriteString("\n" + additionalCSS)
err = ioutil.WriteFile(path.Join(siteDestination, "lib", "style.css"), content, 0755)
err = writeFile(&buf, "lib", "style.css")
if err != nil {
return fmt.Errorf("failed to write index: %s", err)
return fmt.Errorf("failed to write style.css: %s", err)
}
// Write index
@ -446,7 +477,7 @@ func run() error {
log.Println("Writing index...")
}
err = writeIndex(&buf, siteDestination, basePath, siteName, pkgs, filterPkgs)
err = writeIndex(&buf, pkgs, filterPkgs)
if err != nil {
return fmt.Errorf("failed to write index: %s", err)
}
@ -457,6 +488,17 @@ func run() error {
return nil
}
func relativeBasePath(p string) string {
var r string
if p != "" {
r += "../"
}
for i := strings.Count(p, "/"); i > 0; i-- {
r += "../"
}
return r
}
func uniqueStrings(strSlice []string) []string {
keys := make(map[string]bool)
var unique []string

36
page.go
View File

@ -3,7 +3,6 @@ package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
@ -21,7 +20,7 @@ summary { margin-left: 20px; cursor: pointer; }
#footer > p, #footer > li { max-width: none; word-wrap: normal; }
`
const footerText = `Documentation generated with <a href="https://godoc.org/golang.org/x/tools/godoc" target="_blank">godoc</a> + <a href="https://gitlab.com/tslocum/godoc-static" target="_blank">godoc-static</a>`
const footerText = `Generated by <a href="https://godoc.org/golang.org/x/tools/godoc" target="_blank">godoc</a> + <a href="https://gitlab.com/tslocum/godoc-static" target="_blank">godoc-static</a>`
func topBar(basePath string, siteName string) string {
var index string
@ -34,11 +33,30 @@ func topBar(basePath string, siteName string) string {
<div class="top-heading" id="heading-narrow"><a href="` + basePath + index + `">` + siteName + `</a></div>
<!--<a href="#" id="menu-button"><span id="menu-button-arrow">&#9661;</span></a>-->
<div id="menu">
<a href="` + basePath + index + `" style="margin-right: 10px;">Packages</a>
<a href="` + basePath + index + `" style="margin-right: 10px;">Package Index</a>
</div>
</div>`
}
func siteFooterText(basePath string) string {
footer := siteFooter
addP := footer != ""
if addP {
footer += "<p>"
}
if siteZip != "" {
footer += `<a href="` + basePath + siteZip + `">Download ` + siteZip + `</a> to browse offline - `
}
footer += footerText
if addP {
footer += "</p>"
}
return footer
}
func updatePage(doc *goquery.Document, basePath string, siteName string) {
doc.Find("link").Remove()
doc.Find("script").Remove()
@ -157,10 +175,10 @@ func updatePage(doc *goquery.Document, basePath string, siteName string) {
}
})
doc.Find("#footer").Last().SetHtml(siteFooter)
doc.Find("#footer").Last().SetHtml(siteFooterText(basePath))
}
func writeIndex(buf *bytes.Buffer, outDir string, basePath string, siteName string, pkgs []string, filterPkgs []string) error {
func writeIndex(buf *bytes.Buffer, pkgs []string, filterPkgs []string) error {
var index string
if linkIndex {
index = "/index.html"
@ -174,7 +192,7 @@ func writeIndex(buf *bytes.Buffer, outDir string, basePath string, siteName stri
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#375EAB">
<title>` + siteName + `</title>
<link type="text/css" rel="stylesheet" href="` + basePath + `lib/style.css">
<link type="text/css" rel="stylesheet" href="lib/style.css">
</head>
<body>
@ -182,7 +200,7 @@ func writeIndex(buf *bytes.Buffer, outDir string, basePath string, siteName stri
...
</div><!-- #lowframe -->
<div id="topbar" class="wide">` + topBar(basePath, siteName) + `</div>
<div id="topbar" class="wide">` + topBar("", siteName) + `</div>
<div id="page" class="wide">
<div class="container">
`)
@ -264,12 +282,12 @@ PACKAGEINDEX:
buf.WriteString(`
</table>
</div>
<div id="footer">` + siteFooter + `</div>
<div id="footer">` + siteFooterText("") + `</div>
</div>
</div>
</body>
</html>
`)
return ioutil.WriteFile(path.Join(outDir, "index.html"), buf.Bytes(), 0755)
return writeFile(buf, "", "index.html")
}