Copyright 2020 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package frontend

import (
	
	

	
	
	
	
	
	
	
	
	
	
)
MainDetails contains data needed to render the unit template.
Directories are packages and nested modules relative to the path for the unit.
Licenses contains license metadata used in the header.
NumImports is the number of imports for the package.
CommitTime is time that this version was published, or the time that has elapsed since this version was committed if it was done so recently.
Readme is the rendered readme HTML.
ReadmeOutline is a collection of headings from the readme file used to render the readme outline in the sidebar.
ReadmeLinks are from the "Links" section of this unit's readme file, and are displayed on the right sidebar.
DocLinks are from the "Links" section of the Go package documentation, and are displayed on the right sidebar.
ModuleReadmeLinks are from the "Links" section of this unit's module, if the unit is not itself a module. They are displayed on the right sidebar. See https://golang.org/issue/42968.
ImportedByCount is the number of packages that import this path. When the count is > limit it will read as 'limit+'. This field is not supported when using a datasource proxy.
DocSynopsis is used as the content for the <meta name="Description"> tag on the main unit page.
GOOS and GOARCH are the build context for the doc.
BuildContexts holds the values for build contexts available for the doc.
SourceFiles contains .go files for the package.
RepositoryURL is the URL to the repository containing the package.
SourceURL is the URL to the source of the package.
ExpandReadme is holds the expandable readme state.
ModFileURL is an URL to the mod file.
IsTaggedVersion is true if the version is not a psuedorelease.
IsStableVersion is true if the major version is v1 or greater.
File is a source file for a package.
type File struct {
	Name string
	URL  string
}

func ( context.Context,  internal.DataSource,  *internal.UnitMeta,  bool,  internal.BuildContext) ( *MainDetails,  error) {
	defer middleware.ElapsedStat(, "fetchMainDetails")()

	,  := .GetUnit(, , internal.WithMain, )
	if  != nil {
		return nil, 
	}
	 := getSubdirectories(, .Subdirectories)
	if  != nil {
		return nil, 
	}
	,  := getNestedModules(, , , )
	if  != nil {
		return nil, 
	}
	,  := readmeContent(, )
	if  != nil {
		return nil, 
	}
	var (
		           = &dochtml.Parts{}
		,  []link
		              []*File
		           string
		,        string
		      []internal.BuildContext
	)

There should be at most one Documentation.
	var  *internal.Documentation
	if len(.Documentation) > 0 {
		 = .Documentation[0]
	}

	if  != nil {
		 = .Synopsis
		 = .GOOS
		 = .GOARCH
		 = .BuildContexts
		 := middleware.ElapsedStat(, "DecodePackage")
		,  := godoc.DecodePackage(.Source)
		()
		if  != nil {
Instead of returning a 500, return a 404 so the user can reprocess the documentation.
				log.Errorf(, "fetchMainDetails(%q, %q, %q): %v", .Path, .ModulePath, .Version, )
				return nil, errUnitNotFoundWithoutFetch
			}
			return nil, 
		}

If err is ErrTooLarge, then docBody will have an appropriate message.
		if  != nil && !errors.Is(, dochtml.ErrTooLarge) {
			return nil, 
		}
		for ,  := range .Links {
			 = append(, link{Href: .Href, Body: .Text})
		}
		 = middleware.ElapsedStat(, "sourceFiles")
		 = sourceFiles(, )
		()
If the unit is not a module, fetch the module readme to extract its links. In the unlikely event that the module is redistributable but the unit is not, we will not show the module links on the unit page.
	if .Path != .ModulePath && .IsRedistributable {
		,  := .GetModuleReadme(, .ModulePath, .Version)
		if  != nil && !errors.Is(, derrors.NotFound) {
			return nil, 
		}
		if  == nil {
			,  := processReadme(, , .SourceInfo)
			if  != nil {
				return nil, 
			}
			 = .Links
		}
	}

	,  := version.ParseType(.Version)
	if  != nil {
		return nil, 
	}
	 :=  != version.TypePseudo
	 := semver.Major(.Version) != "v0" &&  == version.TypeRelease
	return &MainDetails{
		ExpandReadme:      ,
		Directories:       unitDirectories(append(, ...)),
		Licenses:          transformLicenseMetadata(.Licenses),
		CommitTime:        absoluteTime(.CommitTime),
		Readme:            .HTML,
		ReadmeOutline:     .Outline,
		ReadmeLinks:       .Links,
		DocLinks:          ,
		ModuleReadmeLinks: ,
		DocOutline:        .Outline,
		DocBody:           .Body,
		DocSynopsis:       ,
		GOOS:              ,
		GOARCH:            ,
		BuildContexts:     ,
		SourceFiles:       ,
		RepositoryURL:     .SourceInfo.RepoURL(),
		SourceURL:         .SourceInfo.DirectoryURL(internal.Suffix(.Path, .ModulePath)),
		MobileOutline:     .MobileOutline,
		NumImports:        .NumImports,
		ImportedByCount:   .NumImportedBy,
		IsPackage:         .IsPackage(),
		ModFileURL:        .SourceInfo.ModuleURL() + "/go.mod",
		IsTaggedVersion:   ,
		IsStableVersion:   ,
	}, nil
}

If there is more than one row but the first is all/all, ignore the others. Should never happen; temporary fix until the DB is cleaned up.
	if len() > 1 && [0].BuildContext() == internal.BuildContextAll {
		return [:1]
If there is only one Documentation and it is linux/amd64, then make it all/all. This is temporary, until the next reprocessing. It assumes a unit with a single linux/amd64 actually has only one build context, and hasn't been reprocessed to have all/all. The only effect of this is to prevent "GOOS=linux, GOARCH=amd64" from appearing at the bottom of the doc. That is wrong in the (rather unlikely) case that the package truly only has doc for linux/amd64, but the bug is only cosmetic.
	if len() == 1 && [0].GOOS == "linux" && [0].GOARCH == "amd64" {
		[0].GOOS = internal.All
		[0].GOARCH = internal.All
	}
	return 
}
readmeContent renders the readme to html and collects the headings into an outline.
func ( context.Context,  *internal.Unit) ( *Readme,  error) {
	defer derrors.Wrap(&, "readmeContent(%q, %q, %q)", .Path, .ModulePath, .Version)
	defer middleware.ElapsedStat(, "readmeContent")()
	if !.IsRedistributable {
		return &Readme{}, nil
	}
	return ProcessReadme(, )
}

const missingDocReplacement = `<p>Documentation is missing.</p>`

func ( context.Context,  *internal.Unit,  *godoc.Package,
	 map[string]string) ( *dochtml.Parts,  error) {
	defer derrors.Wrap(&, "getHTML(%s)", .Path)

	if len(.Documentation[0].Source) > 0 {
		return renderDocParts(, , , )
	}
	log.Errorf(, "unit %s (%s@%s) missing documentation source", .Path, .ModulePath, .Version)
	return &dochtml.Parts{Body: template.MustParseAndExecuteToHTML(missingDocReplacement)}, nil