package main import ( "bytes" "fmt" "os" "os/exec" "path" "strconv" "strings" "github.com/PuerkitoBio/goquery" "golang.org/x/net/html" "golang.org/x/net/html/atom" ) const additionalCSS = ` details { margin-top: 20px; } summary { margin-left: 20px; cursor: pointer; } #footer > p, #footer > li { max-width: none; word-wrap: normal; } ` const footerText = `Generated by godoc + godoc-static` func topBar(basePath string, siteName string) string { var index string if linkIndex { index = "index.html" } return `
` + siteName + `
` + siteName + `
` } func siteFooterText(basePath string) string { footer := siteFooter addP := footer != "" if addP { footer += "

" } if siteZip != "" { footer += `Download ` + siteZip + ` to browse offline - ` } footer += footerText if addP { footer += "

" } return footer } func updatePage(doc *goquery.Document, basePath string, siteName string) { doc.Find("link").Remove() doc.Find("script").Remove() linkTag := &html.Node{ Type: html.ElementNode, DataAtom: atom.Link, Data: "link", Attr: []html.Attribute{ {Key: "type", Val: "text/css"}, {Key: "rel", Val: "stylesheet"}, {Key: "href", Val: basePath + "lib/style.css"}, }, } doc.Find("head").AppendNodes(linkTag) doc.Find("#topbar").First().SetHtml(topBar(basePath, siteName)) importPathDisplay := doc.Find("#short-nav").First().Find("code").First() if importPathDisplay.Length() > 0 { importPathDisplayText := importPathDisplay.Text() if strings.ContainsRune(importPathDisplayText, '.') && strings.HasPrefix(importPathDisplayText, `import "`) && strings.HasSuffix(importPathDisplayText, `"`) { importPath := importPathDisplayText[8 : len(importPathDisplayText)-1] browseImportPath := importPath var browseInsert string if strings.HasPrefix(importPath, "gitlab.com/") { browseInsert = "/-/tree/master" } else if strings.HasPrefix(importPath, "github.com/") || strings.HasPrefix(importPath, "git.sr.ht/") { browseInsert = "/tree/master" } else if strings.HasPrefix(importPath, "bitbucket.org/") || strings.HasPrefix(importPath, "code.rocket9labs.com/") { browseInsert = "/src/master" } if browseInsert != "" { var insertPos int var found int for i, c := range importPath { if c == '/' { found++ if found == 3 { insertPos = i break } } } if insertPos > 0 { browseImportPath = importPath[0:insertPos] + browseInsert + importPath[insertPos:] } } importPathDisplay.SetHtml(fmt.Sprintf(`import "` + importPath + `"`)) } } doc.Find("a").Each(func(_ int, selection *goquery.Selection) { href := selection.AttrOr("href", "") var suffix string if (strings.HasPrefix(href, "/src/") || strings.HasPrefix(href, "/pkg/")) && path.Ext(href) != "" { suffix = ".html" } else if linkIndex && !(strings.HasPrefix(href, "#") || strings.HasPrefix(href, "?")) && path.Ext(href) == "" { suffix = "/index.html" } if suffix != "" { pos := strings.IndexAny(href, "?#") if pos >= 0 { href = strings.TrimRight(href[0:pos], "/") + suffix + href[pos:] } else { href = strings.TrimRight(href, "/") + suffix } } if strings.HasPrefix(href, "/src/") || strings.HasPrefix(href, "/pkg/") { if strings.HasPrefix(href, "/pkg/") { href = href[4:] } selection.SetAttr("href", basePath+href[1:]) } else if suffix != ""{ selection.SetAttr("href", href) } }) doc.Find("div").Each(func(_ int, selection *goquery.Selection) { if selection.HasClass("toggle") { var summary string var err error selection.Find("div").Each(func(_ int, subSelection *goquery.Selection) { if subSelection.HasClass("collapsed") { summary, err = subSelection.Find("span.text").First().Html() if err != nil { summary = "Summary not available" } subSelection.Remove() } }) selection.Find(".toggleButton").Remove() selection.PrependHtml(fmt.Sprintf("%s", summary)) selection.RemoveClass("toggle") selection.Nodes[0].Data = "details" selection.Nodes[0].DataAtom = atom.Details } }) doc.Find("#footer").Last().SetHtml(siteFooterText(basePath)) } func writeIndex(buf *bytes.Buffer, pkgs []string, filterPkgs []string) error { var index string if linkIndex { index = "/index.html" } buf.Reset() buf.WriteString(` ` + siteName + `
...
` + topBar("", siteName) + `
`) if siteDescription != "" { buf.WriteString(siteDescription) } buf.WriteString(`

Packages

`) var padding int var lastPkg string var pkgBuf bytes.Buffer for _, pkg := range pkgs { pkgBuf.Reset() cmd := exec.Command("go", "list", "-find", "-f", `{{ .Doc }}`, pkg) cmd.Env = godocEnv cmd.Dir = os.TempDir() cmd.Stdout = &pkgBuf setDeathSignal(cmd) cmd.Run() // Ignore error pkgLabel := pkg if lastPkg != "" { lastPkgSplit := strings.Split(lastPkg, "/") pkgSplit := strings.Split(pkg, "/") shared := 0 for i := range pkgSplit { if i < len(lastPkgSplit) && strings.ToLower(lastPkgSplit[i]) == strings.ToLower(pkgSplit[i]) { shared++ } } padding = shared * 20 pkgLabel = strings.Join(pkgSplit[shared:], "/") } lastPkg = pkg var linkPackage bool for _, filterPkg := range filterPkgs { if pkg == filterPkg { linkPackage = true break } } buf.WriteString(` `) } buf.WriteString(`
Name Synopsis
`) if !linkPackage { buf.WriteString(pkgLabel) } else { buf.WriteString(`` + pkgLabel + ``) } buf.WriteString(` ` + pkgBuf.String() + `
`) return writeFile(buf, "", "index.html") }