github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/doc/generate.go (about) 1 // Copyright 2021 iLogtail Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package doc 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "os" 21 "path/filepath" 22 "reflect" 23 "sort" 24 ) 25 26 const ( 27 topLevel = "# " 28 secondLevel = "## " 29 lf = "\n" 30 markdownSuffix = ".md" 31 tableSplitor = "|" 32 ) 33 34 type FieldConfig struct { 35 Name string 36 Type string 37 Comment string 38 Default string 39 } 40 41 // Generate plugin doc to the path/category directory. 42 func Generate(path string) { 43 fileName := path + "/plugin-list" + markdownSuffix 44 str := topLevel + "Plugin List" + lf 45 46 var sortedCategories []string 47 for category := range docCenter { 48 sortedCategories = append(sortedCategories, category) 49 } 50 sort.Strings(sortedCategories) 51 for _, category := range sortedCategories { 52 plugins := docCenter[category] 53 home := filepath.Clean(path + "/" + category) 54 _ = os.MkdirAll(home, 0750) 55 str += "- " + category + lf 56 var pluginNames []string 57 for name := range plugins { 58 pluginNames = append(pluginNames, name) 59 } 60 sort.Strings(pluginNames) 61 for _, name := range pluginNames { 62 pluginFile := home + "/" + name + markdownSuffix 63 relativeFile := category + "/" + name + markdownSuffix 64 generatePluginDoc(pluginFile, name, docCenter[category][name]) 65 str += " - [" + name + "](" + relativeFile + ")" + lf 66 } 67 } 68 _ = os.WriteFile(fileName, []byte(str), 0600) 69 } 70 71 func generatePluginDoc(fileName, pluginType string, doc Doc) { 72 str := topLevel + pluginType + lf 73 str += secondLevel + "Description" + lf 74 str += doc.Description() + lf 75 str += secondLevel + "Config" + lf 76 if configs := extractDocConfig(doc); len(configs) > 0 { 77 str += `| field | type | description | default value | 78 | ---- | ---- | ---- | ---- |` 79 for _, config := range configs { 80 str += lf + tableSplitor + config.Name + tableSplitor + config.Type + tableSplitor + config.Comment + tableSplitor + config.Default + tableSplitor 81 } 82 } 83 _ = os.WriteFile(fileName, []byte(str), 0600) 84 } 85 86 func extractDocConfig(doc Doc) (configs []*FieldConfig) { 87 rt := reflect.TypeOf(doc) 88 val := reflect.ValueOf(doc) 89 if rt.Kind() == reflect.Ptr { 90 rt = rt.Elem() 91 val = val.Elem() 92 } 93 overrideName := func(index int, tag string, field *FieldConfig) { 94 name := rt.Field(index).Tag.Get(tag) 95 if name != "" { 96 field.Name = name 97 } 98 } 99 for i := 0; i < rt.NumField(); i++ { 100 if rt.Field(i).PkgPath != "" { 101 continue 102 } 103 field := &FieldConfig{ 104 Name: rt.Field(i).Name, 105 Comment: rt.Field(i).Tag.Get("comment"), 106 } 107 if field.Comment == "" { 108 continue 109 } 110 111 field.Type = rt.Field(i).Type.String() 112 113 overrideName(i, "yaml", field) 114 overrideName(i, "json", field) 115 overrideName(i, "mapstructure", field) 116 117 bytes, err := json.Marshal(val.Field(i).Interface()) 118 if err != nil { 119 panic(fmt.Errorf("cannot extract default value: %+v", err)) 120 } 121 field.Default = string(bytes) 122 configs = append(configs, field) 123 } 124 return 125 }