mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Docs: Render map type fields in generated docs (#62022)
* Render map type in docs * Generate * Clenaup rendering properties * Minor updates * Update maps rendering
This commit is contained in:
parent
517e614661
commit
3c01ae2c9e
@ -13,26 +13,19 @@ title: ServiceAccount kind
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|-----------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `avatarUrl` | string | **Yes** | AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front<br/>of the service account. |
|
||||
| `id` | integer | **Yes** | ID is the unique identifier of the service account in the database. |
|
||||
| `isDisabled` | boolean | **Yes** | IsDisabled indicates if the service account is disabled. |
|
||||
| `login` | string | **Yes** | Login of the service account. |
|
||||
| `name` | string | **Yes** | Name of the service account. |
|
||||
| `orgId` | integer | **Yes** | OrgId is the ID of an organisation the service account belongs to. |
|
||||
| `role` | string | **Yes** | OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'. Possible values are: `Admin`, `Editor`, `Viewer`. |
|
||||
| `tokens` | integer | **Yes** | Tokens is the number of active tokens for the service account.<br/>Tokens are used to authenticate the service account against Grafana. |
|
||||
| `accessControl` | [object](#accesscontrol) | No | AccessControl metadata associated with a given resource. |
|
||||
| `created` | integer | No | Created indicates when the service account was created. |
|
||||
| `teams` | string[] | No | Teams is a list of teams the service account belongs to. |
|
||||
| `updated` | integer | No | Updated indicates when the service account was updated. |
|
||||
|
||||
## accessControl
|
||||
|
||||
AccessControl metadata associated with a given resource.
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|----------|------|----------|-------------|
|
||||
| Property | Type | Required | Description |
|
||||
|-----------------|--------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `avatarUrl` | string | **Yes** | AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front<br/>of the service account. |
|
||||
| `id` | integer | **Yes** | ID is the unique identifier of the service account in the database. |
|
||||
| `isDisabled` | boolean | **Yes** | IsDisabled indicates if the service account is disabled. |
|
||||
| `login` | string | **Yes** | Login of the service account. |
|
||||
| `name` | string | **Yes** | Name of the service account. |
|
||||
| `orgId` | integer | **Yes** | OrgId is the ID of an organisation the service account belongs to. |
|
||||
| `role` | string | **Yes** | OrgRole is a Grafana Organization Role which can be 'Viewer', 'Editor', 'Admin'. Possible values are: `Admin`, `Editor`, `Viewer`. |
|
||||
| `tokens` | integer | **Yes** | Tokens is the number of active tokens for the service account.<br/>Tokens are used to authenticate the service account against Grafana. |
|
||||
| `accessControl` | map[string]boolean | No | AccessControl metadata associated with a given resource. |
|
||||
| `created` | integer | No | Created indicates when the service account was created. |
|
||||
| `teams` | string[] | No | Teams is a list of teams the service account belongs to. |
|
||||
| `updated` | integer | No | Updated indicates when the service account was updated. |
|
||||
|
||||
|
||||
|
@ -13,23 +13,16 @@ title: Team kind
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|-----------------|--------------------------|----------|----------------------------------------------------------|
|
||||
| `created` | integer | **Yes** | Created indicates when the team was created. |
|
||||
| `memberCount` | integer | **Yes** | MemberCount is the number of the team members. |
|
||||
| `name` | string | **Yes** | Name of the team. |
|
||||
| `orgId` | integer | **Yes** | OrgId is the ID of an organisation the team belongs to. |
|
||||
| `permission` | integer | **Yes** | Possible values are: `0`, `1`, `2`, `4`. |
|
||||
| `updated` | integer | **Yes** | Updated indicates when the team was updated. |
|
||||
| `accessControl` | [object](#accesscontrol) | No | AccessControl metadata associated with a given resource. |
|
||||
| `avatarUrl` | string | No | AvatarUrl is the team's avatar URL. |
|
||||
| `email` | string | No | Email of the team. |
|
||||
|
||||
## accessControl
|
||||
|
||||
AccessControl metadata associated with a given resource.
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|----------|------|----------|-------------|
|
||||
| Property | Type | Required | Description |
|
||||
|-----------------|--------------------|----------|----------------------------------------------------------|
|
||||
| `created` | integer | **Yes** | Created indicates when the team was created. |
|
||||
| `memberCount` | integer | **Yes** | MemberCount is the number of the team members. |
|
||||
| `name` | string | **Yes** | Name of the team. |
|
||||
| `orgId` | integer | **Yes** | OrgId is the ID of an organisation the team belongs to. |
|
||||
| `permission` | integer | **Yes** | Possible values are: `0`, `1`, `2`, `4`. |
|
||||
| `updated` | integer | **Yes** | Updated indicates when the team was updated. |
|
||||
| `accessControl` | map[string]boolean | No | AccessControl metadata associated with a given resource. |
|
||||
| `avatarUrl` | string | No | AvatarUrl is the team's avatar URL. |
|
||||
| `email` | string | No | Email of the team. |
|
||||
|
||||
|
||||
|
@ -108,18 +108,44 @@ type templateData struct {
|
||||
// Copied from https://github.com/marcusolsson/json-schema-docs and slightly changed to fit the DocsJenny
|
||||
|
||||
type schema struct {
|
||||
ID string `json:"$id,omitempty"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Schema string `json:"$schema,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Required []string `json:"required,omitempty"`
|
||||
Type PropertyTypes `json:"type,omitempty"`
|
||||
Properties map[string]*schema `json:"properties,omitempty"`
|
||||
Items *schema `json:"items,omitempty"`
|
||||
Definitions map[string]*schema `json:"definitions,omitempty"`
|
||||
Enum []Any `json:"enum"`
|
||||
Default any `json:"default"`
|
||||
ID string `json:"$id,omitempty"`
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
Schema string `json:"$schema,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Required []string `json:"required,omitempty"`
|
||||
Type PropertyTypes `json:"type,omitempty"`
|
||||
Properties map[string]*schema `json:"properties,omitempty"`
|
||||
Items *schema `json:"items,omitempty"`
|
||||
Definitions map[string]*schema `json:"definitions,omitempty"`
|
||||
Enum []Any `json:"enum"`
|
||||
AdditionalProperties *schema `json:"additionalProperties"`
|
||||
Default any `json:"default"`
|
||||
}
|
||||
|
||||
func renderMapType(props *schema) string {
|
||||
if props == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if props.Type.HasType(PropertyTypeObject) {
|
||||
name, anchor := propNameAndAnchor(props.Title, props.Title)
|
||||
return fmt.Sprintf("[%s](#%s)", name, anchor)
|
||||
}
|
||||
|
||||
if props.AdditionalProperties != nil {
|
||||
return "map[string]" + renderMapType(props.AdditionalProperties)
|
||||
}
|
||||
|
||||
if props.Items != nil {
|
||||
return "[]" + renderMapType(props.Items)
|
||||
}
|
||||
|
||||
var types []string
|
||||
for _, t := range props.Type {
|
||||
types = append(types, string(t))
|
||||
}
|
||||
return strings.Join(types, ", ")
|
||||
}
|
||||
|
||||
func jsonToMarkdown(jsonData []byte, tpl string, kindName string) ([]byte, error) {
|
||||
@ -189,6 +215,21 @@ func resolveSchema(schem *schema, root *simplejson.Json) (*schema, error) {
|
||||
*schem.Items = *foo
|
||||
}
|
||||
|
||||
if schem.AdditionalProperties != nil {
|
||||
if schem.AdditionalProperties.Ref != "" {
|
||||
tmp, err := resolveReference(schem.AdditionalProperties.Ref, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*schem.AdditionalProperties = *tmp
|
||||
}
|
||||
foo, err := resolveSchema(schem.AdditionalProperties, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*schem.AdditionalProperties = *foo
|
||||
}
|
||||
|
||||
return schem, nil
|
||||
}
|
||||
|
||||
@ -242,7 +283,7 @@ func (s schema) Markdown(level int) string {
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
if s.Title != "" {
|
||||
if s.Title != "" && s.AdditionalProperties == nil {
|
||||
fmt.Fprintln(&buf, makeHeading(s.Title, level))
|
||||
fmt.Fprintln(&buf)
|
||||
}
|
||||
@ -289,9 +330,9 @@ func findDefinitions(s *schema) []*schema {
|
||||
// properties for them recursively.
|
||||
var objs []*schema
|
||||
|
||||
for k, p := range s.Properties {
|
||||
// Use the identifier as the title.
|
||||
if p.Type.HasType(PropertyTypeObject) {
|
||||
definition := func(k string, p *schema) {
|
||||
if p.Type.HasType(PropertyTypeObject) && p.AdditionalProperties == nil {
|
||||
// Use the identifier as the title.
|
||||
if len(p.Title) == 0 {
|
||||
p.Title = k
|
||||
}
|
||||
@ -312,6 +353,15 @@ func findDefinitions(s *schema) []*schema {
|
||||
}
|
||||
}
|
||||
|
||||
for k, p := range s.Properties {
|
||||
// If a property has AdditionalProperties, then it's a map
|
||||
if p.AdditionalProperties != nil {
|
||||
definition(k, p.AdditionalProperties)
|
||||
}
|
||||
|
||||
definition(k, p)
|
||||
}
|
||||
|
||||
// Sort the object schemas.
|
||||
sort.Slice(objs, func(i, j int) bool {
|
||||
return objs[i].Title < objs[j].Title
|
||||
@ -331,67 +381,36 @@ func printProperties(w io.Writer, s *schema) {
|
||||
|
||||
// Buffer all property rows so that we can sort them before printing them.
|
||||
rows := make([][]string, 0, len(s.Properties))
|
||||
for k, p := range s.Properties {
|
||||
// Generate relative links for objects and arrays of objects.
|
||||
propType := make([]string, 0, len(p.Type))
|
||||
for _, pt := range p.Type {
|
||||
switch pt {
|
||||
case PropertyTypeObject:
|
||||
name, anchor := propNameAndAnchor(k, p.Title)
|
||||
propType = append(propType, fmt.Sprintf("[%s](#%s)", name, anchor))
|
||||
case PropertyTypeArray:
|
||||
if p.Items != nil {
|
||||
for _, pi := range p.Items.Type {
|
||||
if pi == PropertyTypeObject {
|
||||
name, anchor := propNameAndAnchor(k, p.Items.Title)
|
||||
propType = append(propType, fmt.Sprintf("[%s](#%s)[]", name, anchor))
|
||||
} else {
|
||||
propType = append(propType, fmt.Sprintf("%s[]", pi))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
propType = append(propType, string(pt))
|
||||
}
|
||||
default:
|
||||
propType = append(propType, string(pt))
|
||||
}
|
||||
}
|
||||
|
||||
var propTypeStr string
|
||||
if len(propType) == 1 {
|
||||
propTypeStr = propType[0]
|
||||
} else if len(propType) == 2 {
|
||||
propTypeStr = strings.Join(propType, " or ")
|
||||
} else if len(propType) > 2 {
|
||||
propTypeStr = fmt.Sprintf("%s, or %s", strings.Join(propType[:len(propType)-1], ", "), propType[len(propType)-1])
|
||||
}
|
||||
for key, val := range s.Properties {
|
||||
typeStr := propTypeStr(key, val)
|
||||
|
||||
// Emphasize required properties.
|
||||
var required string
|
||||
if in(s.Required, k) {
|
||||
if in(s.Required, key) {
|
||||
required = "**Yes**"
|
||||
} else {
|
||||
required = "No"
|
||||
}
|
||||
|
||||
desc := p.Description
|
||||
desc := val.Description
|
||||
|
||||
if len(p.Enum) > 0 {
|
||||
vals := make([]string, 0, len(p.Enum))
|
||||
for _, e := range p.Enum {
|
||||
if len(val.Enum) > 0 {
|
||||
vals := make([]string, 0, len(val.Enum))
|
||||
for _, e := range val.Enum {
|
||||
vals = append(vals, e.String())
|
||||
}
|
||||
desc += " Possible values are: `" + strings.Join(vals, "`, `") + "`."
|
||||
}
|
||||
|
||||
if p.Default != nil {
|
||||
desc += fmt.Sprintf(" Default: `%v`.", p.Default)
|
||||
if val.Default != nil {
|
||||
desc += fmt.Sprintf(" Default: `%v`.", val.Default)
|
||||
}
|
||||
|
||||
rows = append(rows, []string{fmt.Sprintf("`%s`", k), propTypeStr, required, formatForTable(desc)})
|
||||
rows = append(rows, []string{fmt.Sprintf("`%s`", key), typeStr, required, formatForTable(desc)})
|
||||
}
|
||||
|
||||
// Sort by the required column, then by the name column.
|
||||
// Sort by the required column, then by the key column.
|
||||
sort.Slice(rows, func(i, j int) bool {
|
||||
if rows[i][2] < rows[j][2] {
|
||||
return true
|
||||
@ -406,6 +425,53 @@ func printProperties(w io.Writer, s *schema) {
|
||||
table.Render()
|
||||
}
|
||||
|
||||
func propTypeStr(propName string, propValue *schema) string {
|
||||
// If the property has AdditionalProperties, it is most likely a map type
|
||||
if propValue.AdditionalProperties != nil {
|
||||
mapValue := renderMapType(propValue.AdditionalProperties)
|
||||
return "map[string]" + mapValue
|
||||
}
|
||||
|
||||
propType := make([]string, 0, len(propValue.Type))
|
||||
// Generate relative links for objects and arrays of objects.
|
||||
for _, pt := range propValue.Type {
|
||||
switch pt {
|
||||
case PropertyTypeObject:
|
||||
name, anchor := propNameAndAnchor(propName, propValue.Title)
|
||||
propType = append(propType, fmt.Sprintf("[%s](#%s)", name, anchor))
|
||||
case PropertyTypeArray:
|
||||
if propValue.Items != nil {
|
||||
for _, pi := range propValue.Items.Type {
|
||||
if pi == PropertyTypeObject {
|
||||
name, anchor := propNameAndAnchor(propName, propValue.Items.Title)
|
||||
propType = append(propType, fmt.Sprintf("[%s](#%s)[]", name, anchor))
|
||||
} else {
|
||||
propType = append(propType, fmt.Sprintf("%s[]", pi))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
propType = append(propType, string(pt))
|
||||
}
|
||||
default:
|
||||
propType = append(propType, string(pt))
|
||||
}
|
||||
}
|
||||
|
||||
if len(propType) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(propType) == 1 {
|
||||
return propType[0]
|
||||
}
|
||||
|
||||
if len(propType) == 2 {
|
||||
return strings.Join(propType, " or ")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s, or %s", strings.Join(propType[:len(propType)-1], ", "), propType[len(propType)-1])
|
||||
}
|
||||
|
||||
func propNameAndAnchor(prop, title string) (string, string) {
|
||||
if len(title) > 0 {
|
||||
return title, strings.ToLower(title)
|
||||
|
Loading…
Reference in New Issue
Block a user