Example #1
0
func pageView(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html")

	id := strings.TrimSpace(r.FormValue("id"))
	if id != "" {
		db := getDatabase()
		d, found := db.FindFullPackage(id)
		if !found {
			pageNotFound(w, r)
			return
		}
		if d.StarCount < 0 {
			d.StarCount = 0
		}
		var descHTML bytesp.Slice
		doc.ToHTML(&descHTML, d.Description, nil)

		if err := templates.ExecuteTemplate(w, "view.html", struct {
			UIUtils
			gcse.HitInfo
			DescHTML      template.HTML
			TotalDocCount int
			StaticRank    int
			ShowReadme    bool
		}{
			HitInfo:       d,
			DescHTML:      template.HTML(descHTML),
			TotalDocCount: db.PackageCount(),
			StaticRank:    d.StaticRank + 1,
			ShowReadme:    len(d.Description) < 10 && len(d.ReadmeData) > 0,
		}); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}
Example #2
0
func main() {
	pkg, err := build.Import("robpike.io/ivy", "", build.ImportComment)
	if err != nil {
		log.Fatal(err)
	}
	fs := token.NewFileSet()
	pkgs, err := parser.ParseDir(fs, pkg.Dir, nil, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	astPkg := pkgs[pkg.Name]
	if astPkg == nil {
		log.Fatalf("failed to locate %s package", pkg.Name)
	}

	docPkg := doc.New(astPkg, pkg.ImportPath, doc.AllDecls)

	htmlBuf := new(bytes.Buffer)
	fmt.Fprintln(htmlBuf, `<!-- auto-generated from robpike.io/ivy package doc -->`)
	fmt.Fprintln(htmlBuf, head)
	fmt.Fprintln(htmlBuf, `<body>`)
	doc.ToHTML(htmlBuf, docPkg.Doc, nil)
	fmt.Fprintln(htmlBuf, `</body></html>`)

	goBuf := new(bytes.Buffer)
	fmt.Fprintf(goBuf, "package mobile\n\n")
	fmt.Fprintf(goBuf, "// GENERATED; DO NOT EDIT\n")
	fmt.Fprintf(goBuf, "const help = `%s`\n", sanitize(htmlBuf.Bytes()))

	buf, err := format.Source(goBuf.Bytes())
	if err != nil {
		log.Fatalf("failed to gofmt: %v", err)
	}
	os.Stdout.Write(buf)
}
Example #3
0
File: godoc.go Project: ssrl/go
// Template formatter for "html-comment" format.
func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {
	var buf bytes.Buffer
	writeAny(&buf, fileset(x), x[0])
	// TODO(gri) Provide list of words (e.g. function parameters)
	//           to be emphasized by ToHTML.
	doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping
}
Example #4
0
// commentFn formats a source code comment as HTML.
func commentFn(v string) htemp.HTML {
	var buf bytes.Buffer
	godoc.ToHTML(&buf, v, nil)
	p := buf.Bytes()
	p = replaceAll(p, h3Pat, func(out, src []byte, m []int) []byte {
		out = append(out, src[m[0]:m[1]-1]...)
		out = append(out, '4')
		return out
	})
	p = replaceAll(p, rfcPat, func(out, src []byte, m []int) []byte {
		out = append(out, `<a href="http://tools.ietf.org/html/rfc`...)
		out = append(out, src[m[2]:m[3]]...)
		out = append(out, `">`...)
		out = append(out, src[m[0]:m[1]]...)
		out = append(out, `</a>`...)
		return out
	})
	p = replaceAll(p, packagePat, func(out, src []byte, m []int) []byte {
		path := bytes.TrimRight(src[m[2]:m[3]], ".!?:")
		if !doc.IsValidPath(string(path)) {
			return append(out, src[m[0]:m[1]]...)
		}
		out = append(out, src[m[0]:m[2]]...)
		out = append(out, `<a href="/`...)
		out = append(out, path...)
		out = append(out, `">`...)
		out = append(out, path...)
		out = append(out, `</a>`...)
		out = append(out, src[m[2]+len(path):m[1]]...)
		return out
	})
	return htemp.HTML(p)
}
Example #5
0
func (p *Package) html(text string, scope string, ignored map[string]struct{}) template.HTML {
	var buf bytes.Buffer
	doc.ToHTML(&buf, text, nil)
	var out bytes.Buffer
	p.linkify(&out, buf.String(), scope, ignored)
	return template.HTML(out.String())
}
Example #6
0
func comment_htmlFunc(comment string) string {
	var buf bytes.Buffer
	// TODO(gri) Provide list of words (e.g. function parameters)
	//           to be emphasized by ToHTML.
	doc.ToHTML(&buf, comment, nil) // does html-escaping
	return buf.String()
}
Example #7
0
// commentFn formats a source code comment as HTML.
func commentFn(v string) string {
	var buf bytes.Buffer
	godoc.ToHTML(&buf, v, nil)
	p := buf.Bytes()
	p = bytes.Replace(p, h3Open, h4Open, -1)
	p = bytes.Replace(p, h3Close, h4Close, -1)
	p = rfcRE.ReplaceAll(p, rfcReplace)
	return string(p)
}
Example #8
0
func pageView(w http.ResponseWriter, r *http.Request) {
	id := strings.TrimSpace(r.FormValue("id"))
	if id != "" {
		c := appengine.NewContext(r)
		ddb := NewCachedDocDB(c, "doc")
		var doc DocInfo
		err, exists := ddb.Get(id, &doc)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if !exists {
			fmt.Fprintf(w, `<html><body>No such entry!`)

			ent, _ := findCrawlingEntry(c, kindCrawlerPackage, id)
			if ent != nil {
				fmt.Fprintf(w, ` Scheduled to be crawled at %s`,
					ent.ScheduleTime.Format("2006-01-02 15:04:05"))
			} else {
				fmt.Fprintf(w, ` Not found yet!`)
			}
			fmt.Fprintf(w, ` Click to <a href="crawl?id=%s">crawl</a>.</body></html>`,
				template.URLQueryEscaper(id))
			return
		}

		if doc.StarCount < 0 {
			doc.StarCount = 0
		}

		var descHTML villa.ByteSlice
		godoc.ToHTML(&descHTML, doc.Description, nil)

		showReadme := len(doc.Description) < 10 && len(doc.ReadmeData) > 0

		err = templates.ExecuteTemplate(w, "view.html", struct {
			DocInfo
			DescHTML   template.HTML
			ShowReadme bool
		}{
			DocInfo:    doc,
			DescHTML:   template.HTML(descHTML),
			ShowReadme: showReadme,
		})
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}
Example #9
0
// commentFn formats a source code comment as HTML.
func commentFn(v string) htemp.HTML {
	var buf bytes.Buffer
	godoc.ToHTML(&buf, v, nil)
	p := buf.Bytes()
	p = replaceAll(p, h3Pat, func(out, src []byte, m []int) []byte {
		out = append(out, `<h4 id="`...)
		out = append(out, src[m[2]:m[3]]...)
		out = append(out, `">`...)
		out = append(out, src[m[4]:m[5]]...)
		out = append(out, ` <a class="permalink" href="#`...)
		out = append(out, src[m[2]:m[3]]...)
		out = append(out, `">&para</a></h4>`...)
		return out
	})
	p = replaceAll(p, rfcPat, func(out, src []byte, m []int) []byte {
		out = append(out, `<a href="http://tools.ietf.org/html/rfc`...)
		out = append(out, src[m[2]:m[3]]...)

		// If available, add major section fragment
		if m[6] != -1 {
			out = append(out, `#section-`...)
			out = append(out, src[m[8]:m[9]]...)

			// If available, add minor section fragment
			if m[13] != -1 {
				out = append(out, src[m[12]:m[13]]...)
			}
		}

		out = append(out, `">`...)
		out = append(out, src[m[0]:m[1]]...)
		out = append(out, `</a>`...)
		return out
	})
	p = replaceAll(p, packagePat, func(out, src []byte, m []int) []byte {
		path := bytes.TrimRight(src[m[2]:m[3]], ".!?:")
		if !gosrc.IsValidPath(string(path)) {
			return append(out, src[m[0]:m[1]]...)
		}
		out = append(out, src[m[0]:m[2]]...)
		out = append(out, `<a href="/`...)
		out = append(out, path...)
		out = append(out, `">`...)
		out = append(out, path...)
		out = append(out, `</a>`...)
		out = append(out, src[m[2]+len(path):m[1]]...)
		return out
	})
	return htemp.HTML(p)
}
Example #10
0
// toHTML returns Go documention in HTML format for the main package
// in the current directory. It returns an error if it finds multiple
// packages or a non-main package.
func toHTML() ([]byte, error) {
	dir := "."

	// create a build.Package
	bpkg, err := build.ImportDir(dir, build.ImportComment)
	if err != nil {
		return nil, err
	}

	// create an ast.Package
	fset := token.NewFileSet()
	goFiles := map[string]struct{}{}
	for _, f := range bpkg.GoFiles {
		goFiles[f] = struct{}{}
	}
	for _, f := range bpkg.CgoFiles {
		goFiles[f] = struct{}{}
	}
	filter := func(fi os.FileInfo) bool {
		_, ok := goFiles[fi.Name()]
		return ok
	}
	apkgs, err := parser.ParseDir(fset, dir, filter, parser.ParseComments)
	if err != nil {
		return nil, err
	}
	if len(apkgs) > 1 {
		return nil, errors.New("multiple packages in directory")
	}
	var apkg *ast.Package
	var ok bool
	if apkg, ok = apkgs["main"]; !ok {
		return nil, errors.New("package is a non-main package")
	}

	// create a doc.Package
	dpkg := doc.New(apkg, bpkg.ImportPath, 0)

	// return html
	b := new(bytes.Buffer)
	doc.ToHTML(b, dpkg.Doc, nil)
	return b.Bytes(), nil
}
Example #11
0
func appendHeadings(list []string, comment string) []string {
	var buf bytes.Buffer
	doc.ToHTML(&buf, comment, nil)
	for s := buf.String(); ; {
		i := strings.Index(s, html_h)
		if i < 0 {
			break
		}
		i += len(html_h)
		j := strings.Index(s, html_endh)
		if j < 0 {
			list = append(list, s[i:]) // incorrect HTML
			break
		}
		list = append(list, s[i:j])
		s = s[j+len(html_endh):]
	}
	return list
}
Example #12
0
func pageView(w http.ResponseWriter, r *http.Request) {
	id := strings.TrimSpace(r.FormValue("id"))
	if id != "" {
		var doc gcse.HitInfo
		if !findPackage(id, &doc) {
			http.Error(w, fmt.Sprintf("Package %s not found!", id), http.StatusNotFound)
			return
		}
		indexDB, _ := indexDBBox.Get().(*index.TokenSetSearcher)
		if doc.StarCount < 0 {
			doc.StarCount = 0
		}

		var descHTML bytesp.Slice
		godoc.ToHTML(&descHTML, doc.Description, nil)

		showReadme := len(doc.Description) < 10 && len(doc.ReadmeData) > 0

		docCount := 0
		if indexDB != nil {
			docCount = indexDB.DocCount()
		}
		if err := templates.ExecuteTemplate(w, "view.html", struct {
			UIUtils
			gcse.HitInfo
			DescHTML      template.HTML
			TotalDocCount int
			StaticRank    int
			ShowReadme    bool
		}{
			HitInfo:       doc,
			DescHTML:      template.HTML(descHTML),
			TotalDocCount: docCount,
			StaticRank:    doc.StaticRank + 1,
			ShowReadme:    showReadme,
		}); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}
Example #13
0
func commentToHTML(comment string) string {
	b := bytes.NewBuffer(make([]byte, 0, 128))
	doc.ToHTML(b, []byte(comment), nil)
	return b.String()
}
Example #14
0
func renderDoc(render macaron.Render, pdoc *Package, docPath string) error {
	data := make(map[string]interface{})
	data["PkgFullIntro"] = pdoc.Doc

	exports := make([]exportSearchObject, 0, 10)

	var buf bytes.Buffer
	links := make([]*Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.TestImports)+
		len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		exports = append(exports, exportSearchObject{t.Name})
		// buf.WriteString("'" + t.Name + "',")
	}

	for _, f := range pdoc.Funcs {
		f.Code = template.HTMLEscapeString(f.Code)
		links = append(links, &Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		exports = append(exports, exportSearchObject{f.Name})
		// buf.WriteString("'" + f.Name + "',")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			exports = append(exports, exportSearchObject{f.Name})
			// buf.WriteString("'" + f.Name + "',")
		}

		for _, m := range t.Methods {
			exports = append(exports, exportSearchObject{t.Name + "." + m.Name})
			// buf.WriteString("'" + t.Name + "_" + m.Name + "',")
		}
	}

	// Ignore C.
	for _, v := range append(pdoc.Imports, pdoc.TestImports...) {
		if v != "C" {
			links = append(links, &Link{
				Name: path.Base(v) + ".",
				Path: v,
			})
		}
	}

	// Set exported objects type-ahead.
	// exportDataSrc := buf.String()
	if len(exports) > 0 {
		pdoc.IsHasExport = true
		data["IsHasExports"] = true
		exportDataSrc, _ := json.Marshal(exports)
		data["ExportDataSrc"] = "<script>var exportDataSrc = " + string(exportDataSrc) + ";</script>"
	}

	pdoc.IsHasConst = len(pdoc.Consts) > 0
	pdoc.IsHasVar = len(pdoc.Vars) > 0
	if len(pdoc.Examples) > 0 {
		pdoc.IsHasExample = true
		data["IsHasExample"] = pdoc.IsHasExample
		data["Examples"] = pdoc.Examples
	}

	// Constants.
	data["IsHasConst"] = pdoc.IsHasConst
	data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		if len(v.Doc) > 0 {
			buf.Reset()
			doc.ToHTML(&buf, v.Doc, nil)
			v.Doc = buf.String()
		}
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	data["IsHasVar"] = pdoc.IsHasVar
	data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		if len(v.Doc) > 0 {
			buf.Reset()
			doc.ToHTML(&buf, v.Doc, nil)
			v.Doc = buf.String()
		}
		buf.Reset()
		FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Files.
	if len(pdoc.Files) > 0 {
		pdoc.IsHasFile = true
		data["IsHasFiles"] = pdoc.IsHasFile
		data["Files"] = pdoc.Files

		var query string
		if i := strings.Index(pdoc.Files[0].BrowseUrl, "?"); i > -1 {
			query = pdoc.Files[0].BrowseUrl[i:]
		}

		viewFilePath := path.Dir(pdoc.Files[0].BrowseUrl) + "/" + query
		// GitHub URL change.
		if strings.HasPrefix(viewFilePath, "github.com") {
			viewFilePath = strings.Replace(viewFilePath, "blob/", "tree/", 1)
		}
		data["ViewFilePath"] = viewFilePath
	}

	var err error
	renderFuncs(pdoc)

	data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		if len(f.Doc) > 0 {
			buf.Reset()
			doc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
		}
		buf.Reset()
		FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String() + " {"
		if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
			f.Examples = exs
		}
		pdoc.Funcs[i] = f
	}

	data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, v := range t.Consts {
			if len(v.Doc) > 0 {
				buf.Reset()
				doc.ToHTML(&buf, v.Doc, nil)
				v.Doc = buf.String()
			}
			buf.Reset()
			v.Decl = template.HTMLEscapeString(v.Decl)
			v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
			FormatCode(&buf, &v.Decl, links)
			v.FmtDecl = buf.String()
			t.Consts[j] = v
		}
		for j, v := range t.Vars {
			if len(v.Doc) > 0 {
				buf.Reset()
				doc.ToHTML(&buf, v.Doc, nil)
				v.Doc = buf.String()
			}
			buf.Reset()
			FormatCode(&buf, &v.Decl, links)
			v.FmtDecl = buf.String()
			t.Vars[j] = v
		}

		for j, f := range t.Funcs {
			if len(f.Doc) > 0 {
				buf.Reset()
				doc.ToHTML(&buf, f.Doc, nil)
				f.Doc = buf.String()
			}
			buf.Reset()
			FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String() + " {"
			if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
				f.Examples = exs
			}
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			if len(m.Doc) > 0 {
				buf.Reset()
				doc.ToHTML(&buf, m.Doc, nil)
				m.Doc = buf.String()
			}
			buf.Reset()
			FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String() + " {"
			if exs := getExamples(pdoc, t.Name, m.Name); len(exs) > 0 {
				m.Examples = exs
			}
			t.Methods[j] = m
		}
		if len(t.Doc) > 0 {
			buf.Reset()
			doc.ToHTML(&buf, t.Doc, nil)
			t.Doc = buf.String()
		}
		buf.Reset()
		FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		if exs := getExamples(pdoc, "", t.Name); len(exs) > 0 {
			t.Examples = exs
		}
		pdoc.Types[i] = t
	}

	// Examples.
	links = append(links, &Link{
		Name: path.Base(pdoc.ImportPath) + ".",
	})

	for _, e := range pdoc.Examples {
		buf.Reset()
		FormatCode(&buf, &e.Code, links)
		e.Code = buf.String()
	}

	data["ProjectPath"] = pdoc.ProjectPath
	data["ImportPath"] = pdoc.ImportPath

	// GitHub redirects non-HTTPS link and Safari loses "#XXX".
	if strings.HasPrefix(pdoc.ProjectPath, "github") {
		data["Secure"] = "s"
	}

	result, err := render.HTMLBytes("docs/tpl", data)
	if err != nil {
		return fmt.Errorf("error rendering HTML: %v", err)
	}

	pdoc.JsNum = SaveDocPage(docPath, result)
	if pdoc.JsNum == -1 {
		return errors.New("Save JS file wasn't successful")
	}
	SavePkgDoc(pdoc.ImportPath, pdoc.Readme)

	data["UtcTime"] = time.Unix(pdoc.Created, 0).UTC()
	// data["TimeSince"] = calTimeSince(time.Unix(pdoc.Created, 0))
	return nil
}
Example #15
0
// Template formatter for "html-comment" format.
func htmlCommentFmt(w io.Writer, x interface{}, format string) {
	var buf bytes.Buffer
	writeAny(&buf, x, false)
	doc.ToHTML(w, buf.Bytes()) // does html-escaping
}
Example #16
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeController, pdoc *doc.Package, q string, lang string) bool {
	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get project name.
	lastIndex := strings.LastIndex(q, "/")
	proName := q[lastIndex+1:]
	if i := strings.Index(proName, "?"); i > -1 {
		proName = proName[:i]
	}
	this.Data["ProName"] = proName

	// Project VCS home page.
	switch {
	case q[:4] == "code": // code.google.com
		if strings.Index(q, "source/") == -1 {
			this.Data["ProPath"] = strings.Replace(q, pdoc.ProjectName, pdoc.ProjectName+"/source/browse", 1)
		} else {
			this.Data["ProPath"] = q
		}
	case q[:3] == "git": // github.com
		if proName != pdoc.ProjectName {
			// Not root.
			this.Data["ProPath"] = strings.Replace(q, proName, "tree/master/"+proName, 1)
		} else {
			this.Data["ProPath"] = q + "/tree/master"
		}
	}

	this.Data["Views"] = pdoc.Views + 1

	// Remove last "/".
	if urlLen := len(q); q[urlLen-1] == '/' {
		q = q[:urlLen-1]
	}

	if utils.IsGoRepoPath(pdoc.ImportPath) {
		this.Data["IsGoRepo"] = true
	}
	pkgDocPath := q[:lastIndex]
	this.Data["ProDocPath"] = pkgDocPath // Upper level project URL.

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath)
	if err != nil {
		beego.Error("SearchController.generatePage(): models.LoadProject()", err)
		return false
	}
	var buf bytes.Buffer
	godoc.ToHTML(&buf, pdecl.Doc, nil)
	pkgInfo := buf.String()
	pkgInfo = strings.Replace(pkgInfo, "<p>", "<p><b>", 1)
	pkgInfo = strings.Replace(pkgInfo, "</p>", "</b></p>", 1)
	this.Data["PkgFullIntro"] = pkgInfo
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("SearchController.generatePage(): ConvertDataFormat", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports))
	// Get all types and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: t.Doc,
		})
	}
	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0
	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		buf.Reset()
		godoc.ToHTML(&buf, f.Doc, nil)
		f.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, f.Code, links)
		f.Code = buf.String()
		pdoc.Funcs[i] = f
	}
	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, f.Code, links)
			f.Code = buf.String()
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			buf.Reset()
			godoc.ToHTML(&buf, m.Doc, nil)
			m.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, m.Code, links)
			m.Code = buf.String()
			t.Methods[j] = m
		}
		buf.Reset()
		godoc.ToHTML(&buf, t.Doc, nil)
		t.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, t.Decl, links)
		t.FmtDecl = buf.String()
		pdoc.Types[i] = t
	}

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		utils.FormatCode(&buf, v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["UtcTime"] = pdoc.Created
	this.Data["GOOS"] = pdecl.Goos
	this.Data["GOARCH"] = pdecl.Goarch
	return true
}
Example #17
0
// commentFmt formats a source code control comment as HTML.
func commentFmt(v string) template.HTML {
	var buf bytes.Buffer
	godoc.ToHTML(&buf, v, nil)
	return template.HTML(buf.String())
}
Example #18
0
// build generates data from source files.
func (w *walker) build(srcs []*source) (*Package, error) {
	// Set created time.
	w.pdoc.Created = time.Now().UTC()

	// Add source files to walker, I skipped references here.
	w.srcs = make(map[string]*source)
	for _, src := range srcs {
		srcName := strings.ToLower(src.name) // For readme comparation.
		switch {
		case strings.HasSuffix(src.name, ".go"):
			w.srcs[src.name] = src
		case len(w.pdoc.Tag) > 0:
			continue // Only save latest readme.
		case strings.HasPrefix(srcName, "readme_zh") || strings.HasPrefix(srcName, "readme_cn"):
			models.SavePkgDoc(w.pdoc.ImportPath, "zh", src.data)
		case strings.HasPrefix(srcName, "readme"):
			models.SavePkgDoc(w.pdoc.ImportPath, "en", src.data)
		}
	}

	w.fset = token.NewFileSet()

	// Find the package and associated files.
	ctxt := build.Context{
		GOOS:          runtime.GOOS,
		GOARCH:        runtime.GOARCH,
		CgoEnabled:    true,
		JoinPath:      path.Join,
		IsAbsPath:     path.IsAbs,
		SplitPathList: func(list string) []string { return strings.Split(list, ":") },
		IsDir:         func(path string) bool { panic("unexpected") },
		HasSubdir:     func(root, dir string) (rel string, ok bool) { panic("unexpected") },
		ReadDir:       func(dir string) (fi []os.FileInfo, err error) { return w.readDir(dir) },
		OpenFile:      func(path string) (r io.ReadCloser, err error) { return w.openFile(path) },
		Compiler:      "gc",
	}

	bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0)
	// Continue if there are no Go source files; we still want the directory info.
	_, nogo := err.(*build.NoGoError)
	if err != nil {
		if nogo {
			err = nil
			beego.Info("doc.walker.build -> No Go Source file")
		} else {
			return w.pdoc, errors.New("doc.walker.build -> " + err.Error())
		}
	}

	// Parse the Go files
	files := make(map[string]*ast.File)
	for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
		file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
		if err != nil {
			beego.Error("doc.walker.build -> parse go files:", err)
			continue
		}
		w.pdoc.Files = append(w.pdoc.Files, name)
		//w.pdoc.SourceSize += len(w.srcs[name].data)
		files[name] = file
	}

	apkg, _ := ast.NewPackage(w.fset, files, simpleImporter, nil)

	// Find examples in the test files.
	for _, name := range append(bpkg.TestGoFiles, bpkg.XTestGoFiles...) {
		file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
		if err != nil {
			beego.Error("doc.walker.build -> find examples:", err)
			continue
		}
		//w.pdoc.TestFiles = append(w.pdoc.TestFiles, &File{Name: name, URL: w.srcs[name].browseURL})
		//w.pdoc.TestSourceSize += len(w.srcs[name].data)
		w.examples = append(w.examples, doc.Examples(file)...)
	}

	//w.vetPackage(apkg)

	mode := doc.Mode(0)
	if w.pdoc.ImportPath == "builtin" {
		mode |= doc.AllDecls
	}

	pdoc := doc.New(apkg, w.pdoc.ImportPath, mode)

	w.pdoc.Synopsis = utils.Synopsis(pdoc.Doc)
	pdoc.Doc = strings.TrimRight(pdoc.Doc, " \t\n\r")
	var buf bytes.Buffer
	doc.ToHTML(&buf, pdoc.Doc, nil)
	w.pdoc.Doc = w.pdoc.Doc + "<br />" + buf.String()
	w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "<p>", "<p><b>", 1)
	w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "</p>", "</b></p>", 1)
	w.pdoc.Doc = base32.StdEncoding.EncodeToString([]byte(w.pdoc.Doc))

	w.pdoc.Examples = w.getExamples("")
	w.pdoc.IsCmd = bpkg.IsCommand()
	w.srcLines = make(map[string][]string)
	w.pdoc.Consts = w.values(pdoc.Consts)
	w.pdoc.Funcs = w.funcs(pdoc.Funcs)
	w.pdoc.Types = w.types(pdoc.Types)
	w.pdoc.Vars = w.values(pdoc.Vars)
	//w.pdoc.Notes = w.notes(pdoc.Notes)

	w.pdoc.Imports = bpkg.Imports
	w.pdoc.TestImports = bpkg.TestImports
	//w.pdoc.XTestImports = bpkg.XTestImports

	beego.Info("doc.walker.build(", pdoc.ImportPath, "), Goroutine #", runtime.NumGoroutine())
	return w.pdoc, err
}
Example #19
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeController, pdoc *doc.Package, q string, lang string) bool {
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath)
	if err != nil {
		beego.Error("HomeController.generatePage():", err)
		return false
	}

	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get VCS name, project name, project home page, and Upper level project URL.
	this.Data["VCS"], this.Data["ProName"], this.Data["ProPath"], this.Data["ProDocPath"] = getVCSInfo(q, pdoc)

	if utils.IsGoRepoPath(pdoc.ImportPath) &&
		strings.Index(pdoc.ImportPath, ".") == -1 {
		this.Data["IsGoRepo"] = true
	}

	this.Data["Views"] = pdoc.Views + 1

	// Tags.
	this.Data["Tags"] = getTags(pdoc.Tags, lang)

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	byts, _ := base32.StdEncoding.DecodeString(pdecl.Doc)
	this.Data["PkgFullIntro"] = string(byts)

	var buf bytes.Buffer
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("HomeController.generatePage(): ConvertDataFormat", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		buf.WriteString("&quot;" + t.Name + "&quot;,")
	}

	for _, f := range pdoc.Funcs {
		links = append(links, &utils.Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		buf.WriteString("&quot;" + f.Name + "&quot;,")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &utils.Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			buf.WriteString("&quot;" + f.Name + "&quot;,")
		}

		for _, m := range t.Methods {
			buf.WriteString("&quot;" + t.Name + "." + m.Name + "&quot;,")
		}
	}

	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	exportDataSrc := buf.String()
	if len(exportDataSrc) > 0 {
		this.Data["HasExports"] = true
		exportDataSrc = exportDataSrc[:len(exportDataSrc)-1]
		// Set export keyword type-ahead.
		this.Data["ExportDataSrc"] = exportDataSrc
	}

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0
	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		buf.Reset()
		godoc.ToHTML(&buf, f.Doc, nil)
		f.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Code, links)
		f.Code = buf.String()
		pdoc.Funcs[i] = f
	}
	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Code, links)
			f.Code = buf.String()
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			buf.Reset()
			godoc.ToHTML(&buf, m.Doc, nil)
			m.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Code, links)
			m.Code = buf.String()
			t.Methods[j] = m
		}
		buf.Reset()
		godoc.ToHTML(&buf, t.Doc, nil)
		t.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		pdoc.Types[i] = t
	}

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	// Tags.
	this.Data["TagsDataSrc"] = tagSet

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["IsImported"] = pdoc.ImportedNum > 0
	this.Data["ImportPid"] = pdoc.ImportPid
	this.Data["ImportedNum"] = pdoc.ImportedNum
	this.Data["UtcTime"] = pdoc.Created
	this.Data["GOOS"] = pdecl.Goos
	this.Data["GOARCH"] = pdecl.Goarch
	return true
}
Example #20
0
func renderDoc(this *HomeRouter, pdoc *hv.Package, q, tag, docPath string) bool {
	this.Data["PkgFullIntro"] = pdoc.Doc

	var buf bytes.Buffer
	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.TestImports)+
		len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		buf.WriteString("'" + t.Name + "',")
	}

	for _, f := range pdoc.Funcs {
		links = append(links, &utils.Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		buf.WriteString("'" + f.Name + "',")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &utils.Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			buf.WriteString("'" + f.Name + "',")
		}

		for _, m := range t.Methods {
			buf.WriteString("'" + t.Name + "." + m.Name + "',")
		}
	}

	// Ignore C.
	for _, v := range append(pdoc.Imports, pdoc.TestImports...) {
		if v != "C" {
			links = append(links, &utils.Link{
				Name: path.Base(v) + ".",
				Path: v,
			})
		}
	}

	// Set exported objects type-ahead.
	exportDataSrc := buf.String()
	if len(exportDataSrc) > 0 {
		pdoc.IsHasExport = true
		this.Data["IsHasExports"] = true
		exportDataSrc = exportDataSrc[:len(exportDataSrc)-1]
		this.Data["ExportDataSrc"] = "<script>$('.search-export').typeahead({local: [" +
			exportDataSrc + "],limit: 10});</script>"
	}

	pdoc.UserExamples = getUserExamples(pdoc.ImportPath)

	pdoc.IsHasConst = len(pdoc.Consts) > 0
	pdoc.IsHasVar = len(pdoc.Vars) > 0
	if len(pdoc.Examples)+len(pdoc.UserExamples) > 0 {
		pdoc.IsHasExample = true
		this.Data["IsHasExample"] = pdoc.IsHasExample
		this.Data["Examples"] = append(pdoc.Examples, pdoc.UserExamples...)
	}

	// Commented and total objects number.
	var comNum, totalNum int

	// Constants.
	this.Data["IsHasConst"] = pdoc.IsHasConst
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		if len(v.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, v.Doc, nil)
			v.Doc = buf.String()
		}
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["IsHasVar"] = pdoc.IsHasVar
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		if len(v.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, v.Doc, nil)
			v.Doc = buf.String()
		}
		buf.Reset()
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Dirs.
	pinfos := models.GetSubPkgs(pdoc.ImportPath, tag, pdoc.Dirs)
	if len(pinfos) > 0 {
		pdoc.IsHasSubdir = true
		this.Data["IsHasSubdirs"] = pdoc.IsHasSubdir
		this.Data["Subdirs"] = pinfos
		this.Data["ViewDirPath"] = pdoc.ViewDirPath
	}

	// Files.
	if len(pdoc.Files) > 0 {
		pdoc.IsHasFile = true
		this.Data["IsHasFiles"] = pdoc.IsHasFile
		this.Data["Files"] = pdoc.Files

		var query string
		if i := strings.Index(pdoc.Files[0].BrowseUrl, "?"); i > -1 {
			query = pdoc.Files[0].BrowseUrl[i:]
		}
		this.Data["ViewFilePath"] = path.Dir(pdoc.Files[0].BrowseUrl) + "/" + query
	}

	var err error
	pfuncs := doc.RenderFuncs(pdoc)

	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		if len(f.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String() + " {"
		if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
			f.Examples = exs
		}
		totalNum++
		pdoc.Funcs[i] = f
	}

	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, v := range t.Consts {
			if len(v.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, v.Doc, nil)
				v.Doc = buf.String()
			}
			buf.Reset()
			v.Decl = template.HTMLEscapeString(v.Decl)
			v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
			utils.FormatCode(&buf, &v.Decl, links)
			v.FmtDecl = buf.String()
			t.Consts[j] = v
		}
		for j, v := range t.Vars {
			if len(v.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, v.Doc, nil)
				v.Doc = buf.String()
			}
			buf.Reset()
			utils.FormatCode(&buf, &v.Decl, links)
			v.FmtDecl = buf.String()
			t.Vars[j] = v
		}

		for j, f := range t.Funcs {
			if len(f.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, f.Doc, nil)
				f.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String() + " {"
			if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
				f.Examples = exs
			}
			totalNum++
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			if len(m.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, m.Doc, nil)
				m.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String() + " {"
			if exs := getExamples(pdoc, t.Name, m.Name); len(exs) > 0 {
				m.Examples = exs
			}
			totalNum++
			t.Methods[j] = m
		}
		if len(t.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, t.Doc, nil)
			t.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		if exs := getExamples(pdoc, "", t.Name); len(exs) > 0 {
			t.Examples = exs
		}
		totalNum++
		pdoc.Types[i] = t
	}

	if !pdoc.IsCmd {
		// Calculate documentation complete %.
		this.Data["DocCPLabel"], this.Data["DocCP"] = calDocCP(comNum, totalNum)
	} else {
		this.Data["IsCmd"] = true
	}

	// Examples.
	links = append(links, &utils.Link{
		Name: path.Base(pdoc.ImportPath) + ".",
	})

	for _, e := range pdoc.Examples {
		buf.Reset()
		utils.FormatCode(&buf, &e.Code, links)
		e.Code = buf.String()
	}
	for _, e := range pdoc.UserExamples {
		buf.Reset()
		utils.FormatCode(&buf, &e.Code, links)
		e.Code = buf.String()
	}

	this.Data["ImportPath"] = pdoc.ImportPath

	if len(tag) == 0 && (pdoc.IsCmd || pdoc.IsGoRepo || pdoc.IsGoSubrepo) {
		this.Data["IsHasHv"] = true
	}

	// GitHub redirects non-HTTPS link and Safari loses "#XXX".
	if strings.HasPrefix(pdoc.ImportPath, "github") {
		this.Data["Secure"] = "s"
	}

	this.TplNames = "tpl/docs.tpl"
	data, err := this.RenderBytes()
	if err != nil {
		beego.Error("generatePage(", pdoc.ImportPath, ") -> RenderBytes:", err)
		return false
	}

	n := utils.SaveDocPage(docPath, com.Html2JS(data))
	if n == -1 {
		return false
	}
	pdoc.JsNum = n
	pdoc.Id, err = doc.SaveProject(pdoc, pfuncs)
	if err != nil {
		beego.Error("generatePage(", pdoc.ImportPath, ") -> SaveProject:", err)
		return false
	}

	models.SavePkgDoc(pdoc.ImportPath, pdoc.Readme)

	this.Data["UtcTime"] = pdoc.Created
	this.Data["TimeSince"] = calTimeSince(pdoc.Created)
	return true
}
Example #21
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeRouter, pdoc *doc.Package, q, tag, lang string) bool {
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath, tag)
	if err != nil {
		beego.Error("HomeController.generatePage ->", err)
		return false
	}

	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get VCS name, project name, project home page, and Upper level project URL.
	this.Data["VCS"], this.Data["ProName"], this.Data["ProPath"], this.Data["ProDocPath"] =
		getVCSInfo(q, tag, pdoc)

	if utils.IsGoRepoPath(pdoc.ImportPath) &&
		strings.Index(pdoc.ImportPath, ".") == -1 {
		this.Data["IsGoRepo"] = true
	}

	this.Data["Views"] = pdoc.Views + 1

	// Labels.
	this.Data["Labels"] = getLabels(pdoc.Labels)

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	byts, _ := base32.StdEncoding.DecodeString(
		models.LoadPkgDoc(pdoc.ImportPath, lang, "rm"))
	this.Data["PkgDoc"] = string(byts)
	byts, _ = base32.StdEncoding.DecodeString(pdecl.Doc)
	this.Data["PkgFullIntro"] = string(byts)

	var buf bytes.Buffer
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("HomeController.generatePage -> ConvertDataFormat:", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		buf.WriteString("&quot;" + t.Name + "&quot;,")
	}

	for _, f := range pdoc.Funcs {
		links = append(links, &utils.Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		buf.WriteString("&quot;" + f.Name + "&quot;,")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &utils.Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			buf.WriteString("&quot;" + f.Name + "&quot;,")
		}

		for _, m := range t.Methods {
			buf.WriteString("&quot;" + t.Name + "." + m.Name + "&quot;,")
		}
	}

	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	exportDataSrc := buf.String()
	if len(exportDataSrc) > 0 {
		this.Data["HasExports"] = true
		exportDataSrc = exportDataSrc[:len(exportDataSrc)-1]
		// Set export keyword type-ahead.
		this.Data["ExportDataSrc"] = exportDataSrc
	}

	// Commented and total objects number.
	var comNum, totalNum int

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		if len(f.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Code, links)
		f.Code = buf.String()
		if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
			f.IsHasExam = true
			f.Exams = exs
		}
		totalNum++
		pdoc.Funcs[i] = f
	}

	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			if len(f.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, f.Doc, nil)
				f.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Code, links)
			f.Code = buf.String()
			if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
				f.IsHasExam = true
				f.Exams = exs
			}
			totalNum++
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			if len(m.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, m.Doc, nil)
				m.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Code, links)
			m.Code = buf.String()
			if exs := getExamples(pdoc, t.Name, m.Name); len(exs) > 0 {
				m.IsHasExam = true
				m.Exams = exs
			}
			totalNum++
			t.Methods[j] = m
		}
		if len(t.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, t.Doc, nil)
			t.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		if exs := getExamples(pdoc, "", t.Name); len(exs) > 0 {
			t.IsHasExam = true
			t.Exams = exs
		}
		totalNum++
		pdoc.Types[i] = t
	}

	if !pdoc.IsCmd {
		// Calculate documentation complete %.
		this.Data["DocCPLabel"], this.Data["DocCP"] = calDocCP(comNum, totalNum)

		// Examples.
		this.Data["IsHasExams"] = len(pdoc.Examples)+len(pdoc.UserExamples) > 0
		this.Data["Exams"] = append(pdoc.Examples, pdoc.UserExamples...)

		// Tags.
		this.Data["IsHasTags"] = len(pdoc.Tags) > 1
		if len(tag) == 0 {
			tag = "master"
		}
		this.Data["CurTag"] = tag
		this.Data["Tags"] = pdoc.Tags
	} else {
		this.Data["IsCmd"] = true
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v, tag); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	// Labels.
	this.Data["LabelDataSrc"] = labelSet

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["IsImported"] = pdoc.ImportedNum > 0
	this.Data["ImportPid"] = pdoc.ImportPid
	this.Data["ImportedNum"] = pdoc.ImportedNum
	this.Data["UtcTime"] = pdoc.Created
	return true
}
Example #22
0
// Build generates documentation from given source files through 'WalkType'.
func (w *Walker) Build(wr *WalkRes) (*Package, error) {
	ctxt := build.Context{
		CgoEnabled:  true,
		ReleaseTags: build.Default.ReleaseTags,
		BuildTags:   build.Default.BuildTags,
		Compiler:    "gc",
	}

	if w.Pdoc.PkgDecl == nil {
		w.Pdoc.PkgDecl = &PkgDecl{}
	}

	// Check 'WalkType'.
	switch wr.WalkType {
	case WT_Local:
		// Check root path.
		if len(wr.RootPath) == 0 {
			return nil, errors.New("WT_Local: empty root path")
		} else if !com.IsDir(wr.RootPath) {
			return nil, errors.New("WT_Local: cannot find specific directory or it's a file")
		}

		w.setLocalContext(&ctxt)
		return nil, errors.New("Hasn't supported yet!")
	case WT_Memory:
		// Convert source files.
		w.SrcFiles = make(map[string]*Source)
		w.Pdoc.Readme = make(map[string][]byte)
		for _, src := range wr.Srcs {
			srcName := strings.ToLower(src.Name()) // For readme comparation.
			switch {
			case strings.HasSuffix(src.Name(), ".go"):
				w.SrcFiles[src.Name()] = src
			case len(w.Pdoc.Tag) > 0 || (wr.WalkMode&WM_NoReadme != 0):
				// This means we are not on the latest version of the code,
				// so we do not collect the README files.
				continue
			case strings.HasPrefix(srcName, "readme_zh") || strings.HasPrefix(srcName, "readme_cn"):
				w.Pdoc.Readme["zh"] = src.Data()
			case strings.HasPrefix(srcName, "readme"):
				w.Pdoc.Readme["en"] = src.Data()
			}
		}

		// Check source files.
		if w.SrcFiles == nil {
			return nil, errors.New("WT_Memory: no Go source file")
		}

		w.setMemoryContext(&ctxt)

	default:
		return nil, errors.New("Hasn't supported yet!")
	}

	var err error
	var bpkg *build.Package

	for _, env := range goEnvs {
		ctxt.GOOS = env.GOOS
		ctxt.GOARCH = env.GOARCH

		bpkg, err = ctxt.ImportDir(w.Pdoc.ImportPath, 0)
		// Continue if there are no Go source files; we still want the directory info.
		_, nogo := err.(*build.NoGoError)
		if err != nil {
			if nogo {
				err = nil
			} else {
				return nil, errors.New("hv.Walker.Build -> ImportDir: " + err.Error())
			}
		}
	}

	w.Pdoc.IsCmd = bpkg.IsCommand()
	w.Pdoc.Synopsis = synopsis(bpkg.Doc)

	w.Pdoc.Imports = bpkg.Imports
	w.Pdoc.IsCgo = w.isCgo()
	w.Pdoc.TestImports = bpkg.TestImports

	// Check depth.
	if wr.WalkDepth <= WD_Imports {
		return w.Pdoc, nil
	}

	w.Fset = token.NewFileSet()
	// Parse the Go files
	files := make(map[string]*ast.File)
	for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
		file, err := parser.ParseFile(w.Fset, name, w.SrcFiles[name].Data(), parser.ParseComments)
		if err != nil {
			return nil, errors.New("hv.Walker.Build -> parse Go files: " + err.Error())
			continue
		}
		w.Pdoc.Files = append(w.Pdoc.Files, w.SrcFiles[name])
		w.Pdoc.SourceSize += int64(len(w.SrcFiles[name].Data()))
		files[name] = file
	}

	w.apkg, _ = ast.NewPackage(w.Fset, files, poorMansImporter, nil)

	// Find examples in the test files.
	for _, name := range append(bpkg.TestGoFiles, bpkg.XTestGoFiles...) {
		file, err := parser.ParseFile(w.Fset, name, w.SrcFiles[name].Data(), parser.ParseComments)
		if err != nil {
			return nil, errors.New("hv.Walker.Build -> find examples: " + err.Error())
			continue
		}
		w.Pdoc.TestFiles = append(w.Pdoc.TestFiles, w.SrcFiles[name])
		//w.pdoc.TestSourceSize += len(w.srcs[name].data)

		if wr.WalkMode&WM_NoExample != 0 {
			continue
		}
		w.Examples = append(w.Examples, doc.Examples(file)...)
	}

	mode := doc.Mode(0)
	if w.Pdoc.ImportPath == "builtin" || wr.BuildAll {
		mode |= doc.AllDecls
	}
	pdoc := doc.New(w.apkg, w.Pdoc.ImportPath, mode)

	// Get doc.
	pdoc.Doc = strings.TrimRight(pdoc.Doc, " \t\n\r")
	var buf bytes.Buffer
	doc.ToHTML(&buf, pdoc.Doc, nil)
	w.Pdoc.Doc = buf.String()
	// Highlight first sentence.
	w.Pdoc.Doc = strings.Replace(w.Pdoc.Doc, "<p>", "<p><b>", 1)
	w.Pdoc.Doc = strings.Replace(w.Pdoc.Doc, "</p>", "</b></p>", 1)

	if wr.WalkMode&WM_NoExample == 0 {
		w.getExamples()
	}

	w.SrcLines = make(map[string][]string)
	w.Pdoc.Consts = w.values(pdoc.Consts)
	w.Pdoc.Funcs, w.Pdoc.Ifuncs = w.funcs(pdoc.Funcs)
	w.Pdoc.Types, w.Pdoc.Itypes = w.types(pdoc.Types)
	w.Pdoc.Vars = w.values(pdoc.Vars)
	//w.Pdoc.Notes = w.notes(pdoc.Notes)

	return w.Pdoc, nil
}
Example #23
0
// build generates data from source files.
func (w *walker) build(srcs []*source) (*Package, error) {
	// Set created time.
	w.pdoc.Created = time.Now().UTC()

	// Add source files to walker, I skipped references here.
	w.srcs = make(map[string]*source)
	for _, src := range srcs {
		if strings.HasSuffix(src.name, ".go") {
			w.srcs[src.name] = src
		} else if strings.HasPrefix(strings.ToLower(src.name), "readme") {
			// Readme.
			w.pdoc.Doc = string(src.data)
			if len(w.pdoc.Doc) > 0 {
				if w.pdoc.Doc[0] == '\n' {
					w.pdoc.Doc = w.pdoc.Doc[1:]
				}
				// Remove title and `==========`.
				w.pdoc.Doc = w.pdoc.Doc[strings.Index(w.pdoc.Doc, "\n")+1:]
				if len(w.pdoc.Doc) == 0 {
					continue
				}

				if w.pdoc.Doc[0] == '=' {
					w.pdoc.Doc = w.pdoc.Doc[strings.Index(w.pdoc.Doc, "\n")+1:]
				}
				// Find all picture path of build system.
				for _, m := range buildPicPattern.FindAllString(w.pdoc.Doc, -1) {
					start := strings.Index(m, "http")
					end := strings.Index(m, ")")
					if (start > -1) && (end > -1) && (start < end) {
						picPath := m[start:end]
						w.pdoc.Doc = strings.Replace(w.pdoc.Doc, m, "![]("+picPath+")", 1)
					}
				}
				w.pdoc.Doc = string(blackfriday.MarkdownCommon([]byte(w.pdoc.Doc)))
				w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "h3>", "h5>", -1)
				w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "h2>", "h4>", -1)
				w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "h1>", "h3>", -1)
				w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "<center>", "", -1)
				w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "</center>", "", -1)
				w.pdoc.Doc = "<div style='display:block; padding: 3px; border:1px solid #4F4F4F;'>" + w.pdoc.Doc + "</div>"
			}
		}
	}

	w.fset = token.NewFileSet()

	// Find the package and associated files.
	ctxt := build.Context{
		GOOS:          runtime.GOOS,
		GOARCH:        runtime.GOARCH,
		CgoEnabled:    true,
		JoinPath:      path.Join,
		IsAbsPath:     path.IsAbs,
		SplitPathList: func(list string) []string { return strings.Split(list, ":") },
		IsDir:         func(path string) bool { panic("unexpected") },
		HasSubdir:     func(root, dir string) (rel string, ok bool) { panic("unexpected") },
		ReadDir:       func(dir string) (fi []os.FileInfo, err error) { return w.readDir(dir) },
		OpenFile:      func(path string) (r io.ReadCloser, err error) { return w.openFile(path) },
		Compiler:      "gc",
	}

	bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0)
	// Continue if there are no Go source files; we still want the directory info.
	_, nogo := err.(*build.NoGoError)
	if err != nil {
		if nogo {
			err = nil
			beego.Info("doc.walker.build(): No Go Source file.")
		} else {
			return w.pdoc, errors.New("doc.walker.build(): " + err.Error())
		}
	}

	// Parse the Go files
	files := make(map[string]*ast.File)
	for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
		file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
		if err != nil {
			beego.Error("doc.walker.build().[parse go files]:", err)
			continue
		}
		w.pdoc.Files = append(w.pdoc.Files, name)
		//w.pdoc.SourceSize += len(w.srcs[name].data)
		files[name] = file
	}

	apkg, _ := ast.NewPackage(w.fset, files, simpleImporter, nil)

	// Find examples in the test files.
	// for _, name := range append(bpkg.TestGoFiles, bpkg.XTestGoFiles...) {
	// 	file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
	// 	if err != nil {
	// 		beego.Error("doc.walker.build().[find examples]:", err)
	// 		continue
	// 	}
	// 	//w.pdoc.TestFiles = append(w.pdoc.TestFiles, &File{Name: name, URL: w.srcs[name].browseURL})
	// 	//w.pdoc.TestSourceSize += len(w.srcs[name].data)
	// 	w.examples = append(w.examples, doc.Examples(file)...)
	// }

	//w.vetPackage(apkg)

	mode := doc.Mode(0)
	if w.pdoc.ImportPath == "builtin" {
		mode |= doc.AllDecls
	}

	pdoc := doc.New(apkg, w.pdoc.ImportPath, mode)

	w.pdoc.Synopsis = utils.Synopsis(pdoc.Doc)
	pdoc.Doc = strings.TrimRight(pdoc.Doc, " \t\n\r")
	var buf bytes.Buffer
	doc.ToHTML(&buf, pdoc.Doc, nil)
	w.pdoc.Doc = w.pdoc.Doc + "<br />" + buf.String()
	w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "<p>", "<p><b>", 1)
	w.pdoc.Doc = strings.Replace(w.pdoc.Doc, "</p>", "</b></p>", 1)
	w.pdoc.Doc = base32.StdEncoding.EncodeToString([]byte(w.pdoc.Doc))

	//w.pdoc.Examples = w.getExamples("")
	//w.pdoc.IsCmd = bpkg.IsCommand()
	w.pdoc.GOOS = ctxt.GOOS
	w.pdoc.GOARCH = ctxt.GOARCH

	w.srcLines = make(map[string][]string)
	w.pdoc.Consts = w.values(pdoc.Consts)
	w.pdoc.Funcs = w.funcs(pdoc.Funcs)
	w.pdoc.Types = w.types(pdoc.Types)
	w.pdoc.Vars = w.values(pdoc.Vars)
	//w.pdoc.Notes = w.notes(pdoc.Notes)

	w.pdoc.Imports = bpkg.Imports
	w.pdoc.TestImports = bpkg.TestImports
	//w.pdoc.XTestImports = bpkg.XTestImports

	beego.Info("doc.walker.build(", pdoc.ImportPath, "), Goroutine #", runtime.NumGoroutine())
	return w.pdoc, err
}
Example #24
0
func (g *Grapher) emitDoc(obj types.Object, dc *ast.CommentGroup, docstring, filename string) bool {
	if docstring == "" {
		return false
	}
	if obj == nil {
		var htmlBuf bytes.Buffer
		doc.ToHTML(&htmlBuf, docstring, nil)
		var span [2]uint32
		if dc != nil {
			span = makeSpan(g.program.Fset, dc)
		}
		g.addDoc(&Doc{
			DefKey: nil,
			Format: "text/html",
			Data:   htmlBuf.String(),
			File:   filename,
			Span:   span,
		})
		g.addDoc(&Doc{
			DefKey: nil,
			Format: "text/plain",
			Data:   docstring,
			File:   filename,
			Span:   span,
		})
		return true
	}

	if g.seenDocObjs == nil {
		g.seenDocObjs = make(map[types.Object]struct{})
	}
	if _, seen := g.seenDocObjs[obj]; seen {
		return false
	}
	g.seenDocObjs[obj] = struct{}{}

	key, _, err := g.defInfo(obj)
	if err != nil {
		return false
	}

	if g.seenDocKeys == nil {
		g.seenDocKeys = make(map[string]struct{})
	}
	if _, seen := g.seenDocKeys[key.String()]; seen {
		return false
	}
	g.seenDocKeys[key.String()] = struct{}{}

	var htmlBuf bytes.Buffer
	doc.ToHTML(&htmlBuf, docstring, nil)

	var span [2]uint32
	if dc != nil {
		span = makeSpan(g.program.Fset, dc)
	}

	g.addDoc(&Doc{
		DefKey: key,
		Format: "text/html",
		Data:   htmlBuf.String(),
		File:   filename,
		Span:   span,
	})
	g.addDoc(&Doc{
		DefKey: key,
		Format: "text/plain",
		Data:   docstring,
		File:   filename,
		Span:   span,
	})

	return true
}