github.com/oam-dev/kubevela@v1.9.11/references/docgen/provider.go (about) 1 /* 2 Copyright 2023 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package docgen 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 "io" 24 "strings" 25 "sync" 26 27 "cuelang.org/go/cue" 28 "cuelang.org/go/cue/cuecontext" 29 "golang.org/x/sync/errgroup" 30 ) 31 32 // GenerateProvidersMarkdown generates markdown documentation for providers. 33 func GenerateProvidersMarkdown(ctx context.Context, providers []io.Reader, w io.Writer) error { 34 docs := make([]string, len(providers)) 35 mu := &sync.Mutex{} 36 wg, _ := errgroup.WithContext(ctx) 37 38 for i, provider := range providers { 39 i, provider := i, provider 40 wg.Go(func() error { 41 doc := bytes.NewBuffer(nil) 42 43 if err := GenerateProviderMarkdown(provider, doc); err != nil { 44 return err 45 } 46 47 mu.Lock() 48 docs[i] = doc.String() // stable order 49 mu.Unlock() 50 51 return nil 52 }) 53 } 54 55 if err := wg.Wait(); err != nil { 56 return err 57 } 58 59 _, err := w.Write([]byte(strings.Join(docs, "\n"))) 60 return err 61 } 62 63 // GenerateProviderMarkdown generates markdown documentation for a provider. 64 func GenerateProviderMarkdown(provider io.Reader, w io.Writer) error { 65 const ( 66 providerKey = "#provider" 67 paramsKey = "$params" 68 returnsKey = "$returns" 69 ) 70 71 c := cuecontext.New() 72 73 content, err := io.ReadAll(provider) 74 if err != nil { 75 return fmt.Errorf("failed to read provider file: %w", err) 76 } 77 78 v := c.CompileBytes(content) 79 if v.Err() != nil { 80 return fmt.Errorf("failed to compile provider file: %w", v.Err()) 81 } 82 83 // iter provider methods 84 iter, err := v.Fields(cue.Definitions(true)) 85 if err != nil { 86 return fmt.Errorf("failed to get definition iterator: %w", err) 87 } 88 89 docs, ref, pkg := bytes.NewBuffer(nil), MarkdownReference{}, "" 90 for iter.Next() { 91 item := iter.Value() 92 93 // get package name. TODO(iyear): more elegant 94 if pkg == "" { 95 t, err := item.LookupPath(cue.ParsePath(providerKey)).String() 96 if err != nil { 97 return err 98 } 99 pkg = t 100 } 101 102 // header 103 fmt.Fprintf(docs, "## %s\n", iter.Label()) 104 105 doc, _, err := ref.parseParameters("", item.LookupPath(cue.ParsePath(paramsKey)), "*Params*", 0, true) 106 if err != nil { 107 return err 108 } 109 docs.WriteString(doc) 110 111 doc, _, err = ref.parseParameters("", item.LookupPath(cue.ParsePath(returnsKey)), "*Returns*", 0, true) 112 if err != nil { 113 return err 114 } 115 docs.WriteString(doc) 116 } 117 118 doc := bytes.NewBuffer(nil) 119 fmt.Fprintf(doc, "# %s\n\n", pkg) // package name header 120 doc.Write(docs.Bytes()) 121 doc.WriteString("------\n\n") // footer 122 123 _, err = w.Write(doc.Bytes()) 124 return err 125 }