docs: compact layout, blue/green color coding, 1800px max-width; docs-generator SubParams support
This commit is contained in:
@@ -3,23 +3,36 @@ package types
|
||||
|
||||
// ParamSpec — параметр операции.
|
||||
type ParamSpec struct {
|
||||
ID int `yaml:"id"`
|
||||
Code string `yaml:"code"`
|
||||
DataType string `yaml:"data_type"`
|
||||
Type string `yaml:"type"`
|
||||
Required bool `yaml:"required"`
|
||||
Default interface{} `yaml:"default"`
|
||||
Descr string `yaml:"descr"`
|
||||
Man string `yaml:"man"`
|
||||
RefSvcID *int `yaml:"ref_svc_id"`
|
||||
Func string `yaml:"func"`
|
||||
MinValue *int `yaml:"minvalue"`
|
||||
MaxValue *int `yaml:"maxvalue"`
|
||||
Regex string `yaml:"regex"`
|
||||
ValueList []string `yaml:"value_list"`
|
||||
Unique string `yaml:"unique_scope"`
|
||||
MaxLength *int `yaml:"maxlength"`
|
||||
MinLength *int `yaml:"minlength"`
|
||||
ID int `yaml:"id"`
|
||||
Code string `yaml:"code"`
|
||||
DataType string `yaml:"data_type"`
|
||||
Type string `yaml:"type"`
|
||||
Required bool `yaml:"required"`
|
||||
Default interface{} `yaml:"default"`
|
||||
Descr string `yaml:"descr"`
|
||||
Man string `yaml:"man"`
|
||||
RefSvcID *int `yaml:"ref_svc_id"`
|
||||
Func string `yaml:"func"`
|
||||
MinValue *int `yaml:"minvalue"`
|
||||
MaxValue *int `yaml:"maxvalue"`
|
||||
Regex string `yaml:"regex"`
|
||||
ValueList []string `yaml:"value_list"`
|
||||
Unique string `yaml:"unique_scope"`
|
||||
MaxLength *int `yaml:"maxlength"`
|
||||
MinLength *int `yaml:"minlength"`
|
||||
IsJson bool `yaml:"is_json"`
|
||||
HasSubParams bool `yaml:"has_sub_params"`
|
||||
SubParams []ParamSpec `yaml:"sub_params"`
|
||||
}
|
||||
|
||||
// FixupSubParams устанавливает HasSubParams=true если есть sub_params.
|
||||
func FixupSubParams(params []ParamSpec) {
|
||||
for i := range params {
|
||||
if len(params[i].SubParams) > 0 {
|
||||
params[i].HasSubParams = true
|
||||
FixupSubParams(params[i].SubParams)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OperationSpec — операция сервиса.
|
||||
|
||||
@@ -182,13 +182,13 @@ func exampleBlock(spec types.ServiceSpec, version string, apiEndpoint string) st
|
||||
b.WriteString(fmt.Sprintf("resource \"nubes_%s\" \"baza\" {\n", spec.Name))
|
||||
|
||||
for _, p := range requiredParams {
|
||||
b.WriteString(formatParamLine(p, " ", true))
|
||||
b.WriteString(formatParamOrBlock(p, " ", true))
|
||||
}
|
||||
|
||||
if len(defaultParams) > 0 {
|
||||
b.WriteString("\n # Параметры, имеющие значение по умолчанию, если не меняете - эти параметры не обязательно прописывать в манифесте\n")
|
||||
for _, p := range defaultParams {
|
||||
b.WriteString(formatParamLine(p, " ", false))
|
||||
b.WriteString(formatParamOrBlock(p, " ", false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,9 +205,15 @@ func buildCreateParamsPage(spec types.ServiceSpec, nav string) string {
|
||||
|
||||
b.WriteString("**Обязательные параметры (вводимые пользователем)**\n\n")
|
||||
b.WriteString(renderParamTable(requiredParams, true, true))
|
||||
for _, p := range requiredParams {
|
||||
b.WriteString(renderNestedParams(p))
|
||||
}
|
||||
|
||||
b.WriteString("\n**Параметры, имеющие значение по умолчанию, если не меняете - эти параметры не обязательно прописывать в манифесте**\n")
|
||||
b.WriteString(renderParamTable(defaultParams, false, false))
|
||||
for _, p := range defaultParams {
|
||||
b.WriteString(renderNestedParams(p))
|
||||
}
|
||||
|
||||
lifecycle := spec.Lifecycle
|
||||
if lifecycle.SuspendOnDestroyDefault || lifecycle.AdoptExistingOnCreateDefault {
|
||||
@@ -521,6 +527,57 @@ func formatParamLine(p types.ParamSpec, indent string, requiredOnly bool) string
|
||||
return fmt.Sprintf("%s%s = %s\n", indent, paramCode, value)
|
||||
}
|
||||
|
||||
// formatParamOrBlock форматирует параметр или вложенный HCL-блок (map-fixed).
|
||||
func formatParamOrBlock(p types.ParamSpec, indent string, requiredOnly bool) string {
|
||||
if requiredOnly && !p.Required {
|
||||
return ""
|
||||
}
|
||||
// Для map-fixed генерируем вложенный HCL-блок
|
||||
if p.HasSubParams && len(p.SubParams) > 0 && !p.IsJson {
|
||||
paramCode := ToSnake(p.Code)
|
||||
var b strings.Builder
|
||||
b.WriteString(fmt.Sprintf("%s%s {\n", indent, paramCode))
|
||||
for _, sp := range p.SubParams {
|
||||
spVal := sampleValue(sp)
|
||||
spCode := ToSnake(sp.Code)
|
||||
spComment := strings.TrimSpace(stripHTML(sp.Descr))
|
||||
if spComment == "" {
|
||||
spComment = strings.TrimSpace(stripHTML(sp.Man))
|
||||
}
|
||||
if spComment != "" {
|
||||
b.WriteString(fmt.Sprintf("%s %s = %s # %s\n", indent, spCode, spVal, spComment))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s %s = %s\n", indent, spCode, spVal))
|
||||
}
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("%s}\n", indent))
|
||||
return b.String()
|
||||
}
|
||||
// Для array-map-fixed генерируем dynamic блок
|
||||
if p.HasSubParams && len(p.SubParams) > 0 && p.IsJson {
|
||||
paramCode := ToSnake(p.Code)
|
||||
var b strings.Builder
|
||||
b.WriteString(fmt.Sprintf("%s%s {\n", indent, paramCode))
|
||||
b.WriteString(fmt.Sprintf("%s # Каждый элемент массива — объект с полями:\n", indent))
|
||||
for _, sp := range p.SubParams {
|
||||
spVal := sampleValue(sp)
|
||||
spCode := ToSnake(sp.Code)
|
||||
spComment := strings.TrimSpace(stripHTML(sp.Descr))
|
||||
if spComment == "" {
|
||||
spComment = strings.TrimSpace(stripHTML(sp.Man))
|
||||
}
|
||||
if spComment != "" {
|
||||
b.WriteString(fmt.Sprintf("%s %s = %s # %s\n", indent, spCode, spVal, spComment))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s %s = %s\n", indent, spCode, spVal))
|
||||
}
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("%s}\n", indent))
|
||||
return b.String()
|
||||
}
|
||||
return formatParamLine(p, indent, requiredOnly)
|
||||
}
|
||||
|
||||
func sampleValue(p types.ParamSpec) string {
|
||||
if hasDefault(p.Default) {
|
||||
return formatLiteral(p.Default)
|
||||
@@ -857,3 +914,37 @@ func LoadCloudOutputSnapshot(root string) map[int]types.CloudOutputSnapshot {
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// renderNestedParams рендерит вложенные параметры (map-fixed/array-map-fixed).
|
||||
func renderNestedParams(p types.ParamSpec) string {
|
||||
if !p.HasSubParams || len(p.SubParams) == 0 {
|
||||
return ""
|
||||
}
|
||||
var b strings.Builder
|
||||
label := p.Code
|
||||
if p.IsJson {
|
||||
label += " (array-map-fixed) — элемент"
|
||||
} else {
|
||||
label += " (map-fixed)"
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("\n### %s\n\n", label))
|
||||
b.WriteString("<table class=\"resource-table resource-table-compact resource-table-nested\">\n")
|
||||
b.WriteString("<thead><tr><th>ID</th><th>Code</th><th>Type</th><th>Required</th><th>Default</th><th>Description</th><th>Constraints</th></tr></thead>\n<tbody>\n")
|
||||
for _, sp := range p.SubParams {
|
||||
req := "no"
|
||||
if sp.Required {
|
||||
req = "**yes**"
|
||||
}
|
||||
b.WriteString("<tr>")
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(formatID(sp.ID))))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", formatParamCode(sp.Code)))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", formatTypeCell(sp)))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", req))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", defaultCell(sp.Default)))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(pickTextTable(sp))))
|
||||
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(collectConstraints(sp))))
|
||||
b.WriteString("</tr>\n")
|
||||
}
|
||||
b.WriteString("</tbody></table>\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@@ -130,6 +130,9 @@ func loadSpecs(dir string, ordered []types.ServiceMeta) []types.ServiceSpec {
|
||||
if err := yaml.Unmarshal(b, &spec); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range spec.Operations {
|
||||
types.FixupSubParams(spec.Operations[i].Params)
|
||||
}
|
||||
specsByID[spec.ServiceID] = spec
|
||||
return nil
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user