Imports #
"bytes"
"fmt"
"strconv"
"bytes"
"fmt"
"strings"
"slices"
"strings"
"unicode"
"unicode/utf8"
"bytes"
"fmt"
"strings"
"bytes"
"fmt"
"sort"
"strings"
"unicode/utf8"
"bytes"
"fmt"
"strconv"
"bytes"
"fmt"
"strings"
"slices"
"strings"
"unicode"
"unicode/utf8"
"bytes"
"fmt"
"strings"
"bytes"
"fmt"
"sort"
"strings"
"unicode/utf8"
const _ spanKind = iota
const spanCode
const spanHeading
const spanList
const spanOldHeading
const spanPara
var stdPkgs = []string{...}
An Italic is a string rendered as italicized text.
type Italic string
A Plain is a string rendered as plain text (not italicized).
type Plain string
A spanKind describes the kind of span.
type spanKind int
A Block is block-level content in a doc comment, one of [*Code], [*Heading], [*List], or [*Paragraph].
type Block interface {
block()
}
A Text is text-level content in a doc comment, one of [Plain], [Italic], [*Link], or [*DocLink].
type Text interface {
text()
}
A Code is a preformatted code block.
type Code struct {
Text string
}
A Doc is a parsed Go doc comment.
type Doc struct {
Content []Block
Links []*LinkDef
}
A DocLink is a link to documentation for a Go package or symbol.
type DocLink struct {
Text []Text
ImportPath string
Recv string
Name string
}
A Heading is a doc comment heading.
type Heading struct {
Text []Text
}
A Link is a link to a specific URL.
type Link struct {
Auto bool
Text []Text
URL string
}
A LinkDef is a single link definition.
type LinkDef struct {
Text string
URL string
Used bool
}
A List is a numbered or bullet list. Lists are always non-empty: len(Items) > 0. In a numbered list, every Items[i].Number is a non-empty string. In a bullet list, every Items[i].Number is an empty string.
type List struct {
Items []*ListItem
ForceBlankBefore bool
ForceBlankBetween bool
}
A ListItem is a single item in a numbered or bullet list.
type ListItem struct {
Number string
Content []Block
}
A Paragraph is a paragraph of text.
type Paragraph struct {
Text []Text
}
A Parser is a doc comment parser. The fields in the struct can be filled in before calling [Parser.Parse] in order to customize the details of the parsing process.
type Parser struct {
Words map[string]string
LookupPackage func(name string) (importPath string, ok bool)
LookupSym func(recv string, name string) ok bool
}
A Printer is a doc comment printer. The fields in the struct can be filled in before calling any of the printing methods in order to customize the details of the printing process.
type Printer struct {
HeadingLevel int
HeadingID func(h *Heading) string
DocLinkURL func(link *DocLink) string
DocLinkBaseURL string
TextPrefix string
TextCodePrefix string
TextWidth int
}
type commentPrinter struct {
*Printer
}
An htmlPrinter holds the state needed for printing a [Doc] as HTML.
type htmlPrinter struct {
*Printer
tight bool
}
An mdPrinter holds the state needed for printing a Doc as Markdown.
type mdPrinter struct {
*Printer
headingPrefix string
raw bytes.Buffer
}
parseDoc is parsing state for a single doc comment.
type parseDoc struct {
*Parser
*Doc
links map[string]*LinkDef
lines []string
lookupSym func(recv string, name string) bool
}
A span represents a single span of comment lines (lines[start:end]) of an identified kind (code, heading, paragraph, and so on).
type span struct {
start int
end int
kind spanKind
}
A textPrinter holds the state needed for printing a Doc as plain text.
type textPrinter struct {
*Printer
long strings.Builder
prefix string
codePrefix string
width int
}
BlankBefore reports whether a reformatting of the comment should include a blank line before the list. The default rule is the same as for [BlankBetween]: if the list item content contains any blank lines (meaning at least one item has multiple paragraphs) then the list itself must be preceded by a blank line. A preceding blank line can be forced by setting [List].ForceBlankBefore.
func (l *List) BlankBefore() bool
BlankBetween reports whether a reformatting of the comment should include a blank line between each pair of list items. The default rule is that if the list item content contains any blank lines (meaning at least one item has multiple paragraphs) then list items must themselves be separated by blank lines. Blank line separators can be forced by setting [List].ForceBlankBetween.
func (l *List) BlankBetween() bool
Comment returns the standard Go formatting of the [Doc], without any comment markers.
func (p *Printer) Comment(d *Doc) []byte
DefaultID returns the default anchor ID for the heading h. The default anchor ID is constructed by converting every rune that is not alphanumeric ASCII to an underscore and then adding the prefix “hdr-”. For example, if the heading text is “Go Doc Comments”, the default ID is “hdr-Go_Doc_Comments”.
func (h *Heading) DefaultID() string
DefaultLookupPackage is the default package lookup function, used when [Parser.LookupPackage] is nil. It recognizes names of the packages from the standard library with single-element import paths, such as math, which would otherwise be impossible to name. Note that the go/doc package provides a more sophisticated lookup based on the imports used in the current package.
func DefaultLookupPackage(name string) (importPath string, ok bool)
DefaultURL constructs and returns the documentation URL for l, using baseURL as a prefix for links to other packages. The possible forms returned by DefaultURL are: - baseURL/ImportPath, for a link to another package - baseURL/ImportPath#Name, for a link to a const, func, type, or var in another package - baseURL/ImportPath#Recv.Name, for a link to a method in another package - #Name, for a link to a const, func, type, or var in this package - #Recv.Name, for a link to a method in this package If baseURL ends in a trailing slash, then DefaultURL inserts a slash between ImportPath and # in the anchored forms. For example, here are some baseURL values and URLs they can generate: "/pkg/" → "/pkg/math/#Sqrt" "/pkg" → "/pkg/math#Sqrt" "/" → "/math/#Sqrt" "" → "/math#Sqrt"
func (l *DocLink) DefaultURL(baseURL string) string
HTML returns an HTML formatting of the [Doc]. See the [Printer] documentation for ways to customize the HTML output.
func (p *Printer) HTML(d *Doc) []byte
Markdown returns a Markdown formatting of the Doc. See the [Printer] documentation for ways to customize the Markdown output.
func (p *Printer) Markdown(d *Doc) []byte
Parse parses the doc comment text and returns the *[Doc] form. Comment markers (/* // and */) in the text must have already been removed.
func (p *Parser) Parse(text string) *Doc
Text returns a textual formatting of the [Doc]. See the [Printer] documentation for ways to customize the text output.
func (p *Printer) Text(d *Doc) []byte
autoURL checks whether s begins with a URL that should be hyperlinked. If so, it returns the URL, which is a prefix of s, and ok == true. Otherwise it returns "", false. The caller should skip over the first len(url) bytes of s before further processing.
func autoURL(s string) (url string, ok bool)
blankBefore reports whether the block x requires a blank line before it. All blocks do, except for Lists that return false from x.BlankBefore().
func blankBefore(x Block) bool
func (*Paragraph) block()
block prints the block x to out.
func (p *htmlPrinter) block(out *bytes.Buffer, x Block)
block prints the block x to out.
func (p *textPrinter) block(out *bytes.Buffer, x Block)
func (*Code) block()
func (*Heading) block()
block prints the block x to out.
func (p *commentPrinter) block(out *bytes.Buffer, x Block)
func (*List) block()
block prints the block x to out.
func (p *mdPrinter) block(out *bytes.Buffer, x Block)
code returns a code block built from the lines.
func (d *parseDoc) code(lines []string) *Code
commonPrefix returns the longest common prefix of a and b.
func commonPrefix(a string, b string) string
docLink parses text, which was found inside [ ] brackets, as a doc link if possible, returning the DocLink and ok == true or else nil, false. The before and after strings are the text before the [ and after the ] on the same line. Doc links must be preceded and followed by punctuation, spaces, tabs, or the start or end of a line.
func (d *parseDoc) docLink(text string, before string, after string) (link *DocLink, ok bool)
func (p *Printer) docLinkURL(link *DocLink) string
escape prints s to out as plain text, escaping < & " ' and > to avoid being misinterpreted in larger HTML constructs.
func (p *htmlPrinter) escape(out *bytes.Buffer, s string)
escape prints s to out as plain text, escaping special characters to avoid being misinterpreted as Markdown markup sequences.
func (p *mdPrinter) escape(out *bytes.Buffer, s string)
heading returns the *Heading for the given new-style section heading line.
func (d *parseDoc) heading(line string) Block
func (p *Printer) headingID(h *Heading) string
func (p *Printer) headingLevel() int
ident checks whether s begins with a Go identifier. If so, it returns the identifier, which is a prefix of s, and ok == true. Otherwise it returns "", false. The caller should skip over the first len(id) bytes of s before further processing.
func ident(s string) (id string, ok bool)
func importPathOK(c byte) bool
inc increments the decimal string s. For example, inc("1199") == "1200".
func inc(s string) string
indent prints s to out, indenting with the indent string after each newline in s.
func (p *commentPrinter) indent(out *bytes.Buffer, indent string, s string)
indented reports whether line is indented (starts with a leading space or tab).
func indented(line string) bool
isBlank reports whether s is a blank line.
func isBlank(s string) bool
isHeading reports whether line is a new-style section heading.
func isHeading(line string) bool
isHost reports whether c is a byte that can appear in a URL host, like www.example.com or user@[::1]:8080
func isHost(c byte) bool
isIdentASCII reports whether c is an ASCII identifier byte.
func isIdentASCII(c byte) bool
isList reports whether the line is the first line of a list, meaning starts with a list marker after any indentation. (The caller is responsible for checking the line is indented, as appropriate.)
func isList(line string) bool
isName reports whether s is a capitalized Go identifier (like Name).
func isName(s string) bool
isOldHeading reports whether line is an old-style section heading. line is all[off].
func isOldHeading(line string, all []string, off int) bool
isPath reports whether c is a (non-punctuation) path byte.
func isPath(c byte) bool
isPunct reports whether c is a punctuation byte that can appear inside a path but not at the end.
func isPunct(c byte) bool
isScheme reports whether s is a recognized URL scheme. Note that if strings of new length (beyond 3-7) are added here, the fast path at the top of autoURL will need updating.
func isScheme(s string) bool
func isStdPkg(path string) bool
leadingSpace returns the longest prefix of s consisting of spaces and tabs.
func leadingSpace(s string) string
list returns a list built from the indented lines, using forceBlankBefore as the value of the List's ForceBlankBefore field.
func (d *parseDoc) list(lines []string, forceBlankBefore bool) *List
listMarker parses the line as beginning with a list marker. If it can do that, it returns the numeric marker ("" for a bullet list), the rest of the line, and ok == true. Otherwise, it returns "", "", false.
func listMarker(line string) (num string, rest string, ok bool)
lookupPkg is called to look up the pkg in [pkg], [pkg.Name], and [pkg.Name.Recv]. If pkg has a slash, it is assumed to be the full import path and is returned with ok = true. Otherwise, pkg is probably a simple package name like "rand" (not "crypto/rand" or "math/rand"). d.LookupPackage provides a way for the caller to allow resolving such names with reference to the imports in the surrounding package. There is one collision between these two cases: single-element standard library names like "math" are full import paths but don't contain slashes. We let d.LookupPackage have the first chance to resolve it, in case there's a different package imported as math, and otherwise we refer to a built-in list of single-element standard library package names.
func (d *parseDoc) lookupPkg(pkg string) (importPath string, ok bool)
oldHeading returns the *Heading for the given old-style section heading line.
func (d *parseDoc) oldHeading(line string) Block
oneLongLine prints the text sequence x to out as one long line, without worrying about line wrapping. Explicit links have the [ ] dropped to improve readability.
func (p *textPrinter) oneLongLine(out *strings.Builder, x []Text)
paragraph returns a paragraph block built from the lines. If the lines are link definitions, paragraph adds them to d and returns nil.
func (d *parseDoc) paragraph(lines []string) Block
parseLink parses a single link definition line: [text]: url It returns the link definition and whether the line was well formed.
func parseLink(line string) (*LinkDef, bool)
parseLinkedText parses text that is allowed to contain explicit links, such as [math.Sin] or [Go home page], into a slice of Text items. A “pkg” is only assumed to be a full import path if it starts with a domain name (a path element with a dot) or is one of the packages from the standard library (“[os]”, “[encoding/json]”, and so on). To avoid problems with maps, generics, and array types, doc links must be both preceded and followed by punctuation, spaces, tabs, or the start or end of a line. An example problem would be treating map[ast.Expr]TypeAndValue as containing a link.
func (d *parseDoc) parseLinkedText(text string) []Text
func parseSpans(lines []string) []span
parseText parses s as text and returns the result of appending those parsed Text elements to out. parseText does not handle explicit links like [math.Sin] or [Go home page]: those are handled by parseLinkedText. If autoLink is true, then parseText recognizes URLs and words from d.Words and converts those to links as appropriate.
func (d *parseDoc) parseText(out []Text, s string, autoLink bool) []Text
rawText prints the text sequence x to out, without worrying about escaping characters that have special meaning at the start of a Markdown line.
func (p *mdPrinter) rawText(out *bytes.Buffer, x []Text)
If text is of the form before.Name, where Name is a capitalized Go identifier, then splitDocName returns before, name, true. Otherwise it returns text, "", false.
func splitDocName(text string) (before string, name string, foundDot bool)
func (Italic) text()
text prints the text sequence x to out.
func (p *mdPrinter) text(out *bytes.Buffer, x []Text)
func (*DocLink) text()
func (*Link) text()
text prints the text sequence x to out.
func (p *commentPrinter) text(out *bytes.Buffer, indent string, x []Text)
func (Plain) text()
text prints the text sequence x to out.
func (p *htmlPrinter) text(out *bytes.Buffer, x []Text)
text prints the text sequence x to out.
func (p *textPrinter) text(out *bytes.Buffer, indent string, x []Text)
unindent removes any common space/tab prefix from each line in lines, returning a copy of lines in which those prefixes have been trimmed from each line. It also replaces any lines containing only spaces with blank lines (empty strings).
func unindent(lines []string) []string
validImportPath reports whether path is a valid import path. It is a lightly edited copy of golang.org/x/mod/module.CheckImportPath.
func validImportPath(path string) bool
func validImportPathElem(elem string) bool
wrap wraps words into lines of at most max runes, minimizing the sum of the squares of the leftover lengths at the end of each line (except the last, of course), with a preference for ending lines at punctuation (.,:;). The returned slice gives the indexes of the first words on each line in the wrapped text with a final entry of len(words). Thus the lines are words[seq[0]:seq[1]], words[seq[1]:seq[2]], ..., words[seq[len(seq)-2]:seq[len(seq)-1]]. The implementation runs in O(n log n) time, where n = len(words), using the algorithm described in D. S. Hirschberg and L. L. Larmore, “[The least weight subsequence problem],” FOCS 1985, pp. 137-143. [The least weight subsequence problem]: https://doi.org/10.1109/SFCS.1985.60
func wrap(words []string, max int) (seq []int)
wrapPenalty is the penalty for inserting a line break after word s.
func wrapPenalty(s string) int64
writeNL calls out.WriteByte('\n') but first trims trailing spaces on the previous line.
func writeNL(out *bytes.Buffer)
Generated with Arrow