diff --git a/internal/godocfx/parse.go b/internal/godocfx/parse.go index 2d0d09fdd08..f336f03e7ec 100644 --- a/internal/godocfx/parse.go +++ b/internal/godocfx/parse.go @@ -218,7 +218,7 @@ func parse(glob string, optionalExtraFiles []string) (*result, error) { UID: docPkg.ImportPath, Name: docPkg.ImportPath, ID: docPkg.Name, - Summary: docPkg.Doc, + Summary: toHTML(docPkg.Doc), Langs: onlyGo, Type: "package", Examples: processExamples(docPkg.Examples, fset), @@ -456,3 +456,9 @@ func buildTOC(mod string, pkgs []string, extraFiles []string) tableOfContents { return toc } + +func toHTML(s string) string { + buf := &bytes.Buffer{} + doc.ToHTML(buf, s, nil) + return buf.String() +} diff --git a/internal/godocfx/testdata/golden/index.yml b/internal/godocfx/testdata/golden/index.yml index dda787e0dc3..f1af2e1a778 100644 --- a/internal/godocfx/testdata/golden/index.yml +++ b/internal/godocfx/testdata/golden/index.yml @@ -3,7 +3,7 @@ items: - uid: cloud.google.com/go/storage name: cloud.google.com/go/storage id: storage - summary: "Package storage provides an easy way to work with Google Cloud Storage.\nGoogle Cloud Storage stores data in named objects, which are grouped into buckets.\n\nMore information about Google Cloud Storage is available at\nhttps://cloud.google.com/storage/docs.\n\nSee https://godoc.org/cloud.google.com/go for authentication, timeouts,\nconnection pooling and similar aspects of this package.\n\nAll of the methods of this package use exponential backoff to retry calls that fail\nwith certain errors, as described in\nhttps://cloud.google.com/storage/docs/exponential-backoff. Retrying continues\nindefinitely unless the controlling context is canceled or the client is closed. See\ncontext.WithTimeout and context.WithCancel.\n\nCreating a Client\n\nTo start working with this package, create a client:\n\n ctx := context.Background()\n client, err := storage.NewClient(ctx)\n if err != nil {\n // TODO: Handle error.\n }\n\nThe client will use your default application credentials. Clients should be\nreused instead of created as needed. The methods of Client are safe for\nconcurrent use by multiple goroutines.\n\nIf you only wish to access public data, you can create\nan unauthenticated client with\n\n client, err := storage.NewClient(ctx, option.WithoutAuthentication())\n\nBuckets\n\nA Google Cloud Storage bucket is a collection of objects. To work with a\nbucket, make a bucket handle:\n\n bkt := client.Bucket(bucketName)\n\nA handle is a reference to a bucket. You can have a handle even if the\nbucket doesn't exist yet. To create a bucket in Google Cloud Storage,\ncall Create on the handle:\n\n if err := bkt.Create(ctx, projectID, nil); err != nil {\n // TODO: Handle error.\n }\n\nNote that although buckets are associated with projects, bucket names are\nglobal across all projects.\n\nEach bucket has associated metadata, represented in this package by\nBucketAttrs. The third argument to BucketHandle.Create allows you to set\nthe initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use\nAttrs:\n\n attrs, err := bkt.Attrs(ctx)\n if err != nil {\n // TODO: Handle error.\n }\n fmt.Printf(\"bucket %s, created at %s, is located in %s with storage class %s\\n\",\n attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)\n\nObjects\n\nAn object holds arbitrary data as a sequence of bytes, like a file. You\nrefer to objects using a handle, just as with buckets, but unlike buckets\nyou don't explicitly create an object. Instead, the first time you write\nto an object it will be created. You can use the standard Go io.Reader\nand io.Writer interfaces to read and write object data:\n\n obj := bkt.Object(\"data\")\n // Write something to obj.\n // w implements io.Writer.\n w := obj.NewWriter(ctx)\n // Write some text to obj. This will either create the object or overwrite whatever is there already.\n if _, err := fmt.Fprintf(w, \"This object contains text.\\n\"); err != nil {\n // TODO: Handle error.\n }\n // Close, just like writing a file.\n if err := w.Close(); err != nil {\n // TODO: Handle error.\n }\n\n // Read it back.\n r, err := obj.NewReader(ctx)\n if err != nil {\n // TODO: Handle error.\n }\n defer r.Close()\n if _, err := io.Copy(os.Stdout, r); err != nil {\n // TODO: Handle error.\n }\n // Prints \"This object contains text.\"\n\nObjects also have attributes, which you can fetch with Attrs:\n\n objAttrs, err := obj.Attrs(ctx)\n if err != nil {\n // TODO: Handle error.\n }\n fmt.Printf(\"object %s has size %d and can be read using %s\\n\",\n objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)\n\nListing objects\n\nListing objects in a bucket is done with the Bucket.Objects method:\n\n query := &storage.Query{Prefix: \"\"}\n\n var names []string\n it := bkt.Objects(ctx, query)\n for {\n attrs, err := it.Next()\n if err == iterator.Done {\n break\n }\n if err != nil {\n log.Fatal(err)\n }\n names = append(names, attrs.Name)\n }\n\nIf only a subset of object attributes is needed when listing, specifying this\nsubset using Query.SetAttrSelection may speed up the listing process:\n\n query := &storage.Query{Prefix: \"\"}\n query.SetAttrSelection([]string{\"Name\"})\n\n // ... as before\n\nACLs\n\nBoth objects and buckets have ACLs (Access Control Lists). An ACL is a list of\nACLRules, each of which specifies the role of a user, group or project. ACLs\nare suitable for fine-grained control, but you may prefer using IAM to control\naccess at the project level (see\nhttps://cloud.google.com/storage/docs/access-control/iam).\n\nTo list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:\n\n acls, err := obj.ACL().List(ctx)\n if err != nil {\n // TODO: Handle error.\n }\n for _, rule := range acls {\n fmt.Printf(\"%s has role %s\\n\", rule.Entity, rule.Role)\n }\n\nYou can also set and delete ACLs.\n\nConditions\n\nEvery object has a generation and a metageneration. The generation changes\nwhenever the content changes, and the metageneration changes whenever the\nmetadata changes. Conditions let you check these values before an operation;\nthe operation only executes if the conditions match. You can use conditions to\nprevent race conditions in read-modify-write operations.\n\nFor example, say you've read an object's metadata into objAttrs. Now\nyou want to write to that object, but only if its contents haven't changed\nsince you read it. Here is how to express that:\n\n w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)\n // Proceed with writing as above.\n\nSigned URLs\n\nYou can obtain a URL that lets anyone read or write an object for a limited time.\nYou don't need to create a client to do this. See the documentation of\nSignedURL for details.\n\n url, err := storage.SignedURL(bucketName, \"shared-object\", opts)\n if err != nil {\n // TODO: Handle error.\n }\n fmt.Println(url)\n\nPost Policy V4 Signed Request\n\nA type of signed request that allows uploads through HTML forms directly to Cloud Storage with\ntemporary permission. Conditions can be applied to restrict how the HTML form is used and exercised\nby a user.\n\nFor more information, please see https://cloud.google.com/storage/docs/xml-api/post-object as well\nas the documentation of GenerateSignedPostPolicyV4.\n\n pv4, err := storage.GenerateSignedPostPolicyV4(bucketName, objectName, opts)\n if err != nil {\n // TODO: Handle error.\n }\n fmt.Printf(\"URL: %s\\nFields; %v\\n\", pv4.URL, pv4.Fields)\n\nErrors\n\nErrors returned by this client are often of the type [`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error).\nThese errors can be introspected for more information by type asserting to the richer `googleapi.Error` type. For example:\n\n\tif e, ok := err.(*googleapi.Error); ok {\n\t\t if e.Code == 409 { ... }\n\t}\n" + summary: "

\nPackage storage provides an easy way to work with Google Cloud Storage.\nGoogle Cloud Storage stores data in named objects, which are grouped into buckets.\n

\n

\nMore information about Google Cloud Storage is available at\nhttps://cloud.google.com/storage/docs.\n

\n

\nSee https://godoc.org/cloud.google.com/go for authentication, timeouts,\nconnection pooling and similar aspects of this package.\n

\n

\nAll of the methods of this package use exponential backoff to retry calls that fail\nwith certain errors, as described in\nhttps://cloud.google.com/storage/docs/exponential-backoff. Retrying continues\nindefinitely unless the controlling context is canceled or the client is closed. See\ncontext.WithTimeout and context.WithCancel.\n

\n

Creating a Client

\n

\nTo start working with this package, create a client:\n

\n
ctx := context.Background()\nclient, err := storage.NewClient(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\n
\n

\nThe client will use your default application credentials. Clients should be\nreused instead of created as needed. The methods of Client are safe for\nconcurrent use by multiple goroutines.\n

\n

\nIf you only wish to access public data, you can create\nan unauthenticated client with\n

\n
client, err := storage.NewClient(ctx, option.WithoutAuthentication())\n
\n

Buckets

\n

\nA Google Cloud Storage bucket is a collection of objects. To work with a\nbucket, make a bucket handle:\n

\n
bkt := client.Bucket(bucketName)\n
\n

\nA handle is a reference to a bucket. You can have a handle even if the\nbucket doesn't exist yet. To create a bucket in Google Cloud Storage,\ncall Create on the handle:\n

\n
if err := bkt.Create(ctx, projectID, nil); err != nil {\n    // TODO: Handle error.\n}\n
\n

\nNote that although buckets are associated with projects, bucket names are\nglobal across all projects.\n

\n

\nEach bucket has associated metadata, represented in this package by\nBucketAttrs. The third argument to BucketHandle.Create allows you to set\nthe initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use\nAttrs:\n

\n
attrs, err := bkt.Attrs(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("bucket %s, created at %s, is located in %s with storage class %s\\n",\n    attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)\n
\n

Objects

\n

\nAn object holds arbitrary data as a sequence of bytes, like a file. You\nrefer to objects using a handle, just as with buckets, but unlike buckets\nyou don't explicitly create an object. Instead, the first time you write\nto an object it will be created. You can use the standard Go io.Reader\nand io.Writer interfaces to read and write object data:\n

\n
obj := bkt.Object("data")\n// Write something to obj.\n// w implements io.Writer.\nw := obj.NewWriter(ctx)\n// Write some text to obj. This will either create the object or overwrite whatever is there already.\nif _, err := fmt.Fprintf(w, "This object contains text.\\n"); err != nil {\n    // TODO: Handle error.\n}\n// Close, just like writing a file.\nif err := w.Close(); err != nil {\n    // TODO: Handle error.\n}\n\n// Read it back.\nr, err := obj.NewReader(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\ndefer r.Close()\nif _, err := io.Copy(os.Stdout, r); err != nil {\n    // TODO: Handle error.\n}\n// Prints "This object contains text."\n
\n

\nObjects also have attributes, which you can fetch with Attrs:\n

\n
objAttrs, err := obj.Attrs(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("object %s has size %d and can be read using %s\\n",\n    objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)\n
\n

Listing objects

\n

\nListing objects in a bucket is done with the Bucket.Objects method:\n

\n
query := &storage.Query{Prefix: ""}\n\nvar names []string\nit := bkt.Objects(ctx, query)\nfor {\n    attrs, err := it.Next()\n    if err == iterator.Done {\n        break\n    }\n    if err != nil {\n        log.Fatal(err)\n    }\n    names = append(names, attrs.Name)\n}\n
\n

\nIf only a subset of object attributes is needed when listing, specifying this\nsubset using Query.SetAttrSelection may speed up the listing process:\n

\n
query := &storage.Query{Prefix: ""}\nquery.SetAttrSelection([]string{"Name"})\n\n// ... as before\n
\n

ACLs

\n

\nBoth objects and buckets have ACLs (Access Control Lists). An ACL is a list of\nACLRules, each of which specifies the role of a user, group or project. ACLs\nare suitable for fine-grained control, but you may prefer using IAM to control\naccess at the project level (see\nhttps://cloud.google.com/storage/docs/access-control/iam).\n

\n

\nTo list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:\n

\n
acls, err := obj.ACL().List(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfor _, rule := range acls {\n    fmt.Printf("%s has role %s\\n", rule.Entity, rule.Role)\n}\n
\n

\nYou can also set and delete ACLs.\n

\n

Conditions

\n

\nEvery object has a generation and a metageneration. The generation changes\nwhenever the content changes, and the metageneration changes whenever the\nmetadata changes. Conditions let you check these values before an operation;\nthe operation only executes if the conditions match. You can use conditions to\nprevent race conditions in read-modify-write operations.\n

\n

\nFor example, say you've read an object's metadata into objAttrs. Now\nyou want to write to that object, but only if its contents haven't changed\nsince you read it. Here is how to express that:\n

\n
w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)\n// Proceed with writing as above.\n
\n

Signed URLs

\n

\nYou can obtain a URL that lets anyone read or write an object for a limited time.\nYou don't need to create a client to do this. See the documentation of\nSignedURL for details.\n

\n
url, err := storage.SignedURL(bucketName, "shared-object", opts)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Println(url)\n
\n

Post Policy V4 Signed Request

\n

\nA type of signed request that allows uploads through HTML forms directly to Cloud Storage with\ntemporary permission. Conditions can be applied to restrict how the HTML form is used and exercised\nby a user.\n

\n

\nFor more information, please see https://cloud.google.com/storage/docs/xml-api/post-object as well\nas the documentation of GenerateSignedPostPolicyV4.\n

\n
pv4, err := storage.GenerateSignedPostPolicyV4(bucketName, objectName, opts)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("URL: %s\\nFields; %v\\n", pv4.URL, pv4.Fields)\n
\n

Errors

\n

\nErrors returned by this client are often of the type [`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error).\nThese errors can be introspected for more information by type asserting to the richer `googleapi.Error` type. For example:\n

\n
if e, ok := err.(*googleapi.Error); ok {\n\t  if e.Code == 409 { ... }\n}\n
\n" type: package langs: - go