fix: HTML tables → Markdown tables in docs-generator (mkdocs теперь рендерит таблицы корректно)

This commit is contained in:
“Naeel”
2026-08-10 13:12:17 +04:00
parent 8d53a4c499
commit 35aa50f76d
@@ -552,28 +552,26 @@ func renderParamTable(params []types.ParamSpec, requiredTable, noDefault bool) s
return "None.\n" return "None.\n"
} }
var b strings.Builder var b strings.Builder
tableClass := "resource-table resource-table-compact"
if requiredTable {
tableClass += " resource-table-required"
}
b.WriteString(fmt.Sprintf("<table class=\"%s\">\n", tableClass))
if noDefault { if noDefault {
b.WriteString("<thead><tr><th>Code</th><th>Type</th><th>Description</th><th>Constraints</th></tr></thead>\n<tbody>\n") b.WriteString("| Code | Type | Description | Constraints |\n")
b.WriteString("|------|------|-------------|-------------|\n")
} else { } else {
b.WriteString("<thead><tr><th>Code</th><th>Type</th><th>Default</th><th>Description</th><th>Constraints</th></tr></thead>\n<tbody>\n") b.WriteString("| Code | Type | Default | Description | Constraints |\n")
b.WriteString("|------|------|---------|-------------|-------------|\n")
} }
for _, p := range params { for _, p := range params {
b.WriteString("<tr>") code := formatParamCode(p.Code)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatParamCode(p.Code))) dtype := formatTypeCell(p)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatTypeCell(p))) desc := escapeText(pickTextTable(p))
if !noDefault { constr := escapeText(collectConstraints(p))
b.WriteString(fmt.Sprintf("<td>%s</td>", defaultCell(p.Default))) if noDefault {
b.WriteString(fmt.Sprintf("| %s | %s | %s | %s |\n", code, dtype, desc, constr))
} else {
def := defaultCell(p.Default)
b.WriteString(fmt.Sprintf("| %s | %s | %s | %s | %s |\n", code, dtype, def, desc, constr))
} }
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(pickTextTable(p))))
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(collectConstraints(p))))
b.WriteString("</tr>\n")
} }
b.WriteString("</tbody></table>\n") b.WriteString("\n")
return b.String() return b.String()
} }
@@ -582,17 +580,16 @@ func renderModifyTable(params []types.ParamSpec) string {
return "None.\n" return "None.\n"
} }
var b strings.Builder var b strings.Builder
b.WriteString("<table class=\"resource-table resource-table-compact\">\n") b.WriteString("| Code | Type | Description | Constraints |\n")
b.WriteString("<thead><tr><th>Code</th><th>Type</th><th>Description</th><th>Constraints</th></tr></thead>\n<tbody>\n") b.WriteString("|------|------|-------------|-------------|\n")
for _, p := range params { for _, p := range params {
b.WriteString("<tr>") code := formatParamCode(p.Code)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatParamCode(p.Code))) dtype := formatTypeCell(p)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatTypeCell(p))) desc := escapeText(pickTextTable(p))
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(pickTextTable(p)))) constr := escapeText(collectConstraints(p))
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(collectConstraints(p)))) b.WriteString(fmt.Sprintf("| %s | %s | %s | %s |\n", code, dtype, desc, constr))
b.WriteString("</tr>\n")
} }
b.WriteString("</tbody></table>\n") b.WriteString("\n")
return b.String() return b.String()
} }
@@ -750,7 +747,7 @@ func formatTypeCell(p types.ParamSpec) string {
if dtype == "" { if dtype == "" {
return "" return ""
} }
return "<code>" + escapeText(dtype) + "</code>" return "`" + dtype + "`"
} }
func firstType(p types.ParamSpec) string { func firstType(p types.ParamSpec) string {
@@ -777,9 +774,9 @@ func defaultCell(value interface{}) string {
return "" return ""
} }
if s, ok := value.(string); ok { if s, ok := value.(string); ok {
return "<code>" + escapeText(s) + "</code>" return "`" + s + "`"
} }
return "<code>" + escapeText(formatLiteral(value)) + "</code>" return "`" + formatLiteral(value) + "`"
} }
func pickTextTable(p types.ParamSpec) string { func pickTextTable(p types.ParamSpec) string {
@@ -869,35 +866,19 @@ func escapeText(value string) string {
text = strings.ReplaceAll(text, "&lt;br/&gt;", "<br/>") text = strings.ReplaceAll(text, "&lt;br/&gt;", "<br/>")
text = strings.ReplaceAll(text, "&lt;br /&gt;", "<br/>") text = strings.ReplaceAll(text, "&lt;br /&gt;", "<br/>")
text = strings.ReplaceAll(text, "&lt;br&gt;", "<br/>") text = strings.ReplaceAll(text, "&lt;br&gt;", "<br/>")
// Escape pipe for markdown tables
text = strings.ReplaceAll(text, "|", "\\|")
// Replace literal newlines with <br/> for markdown table cells
text = strings.ReplaceAll(text, "\n", "<br/>")
return text return text
} }
func formatParamCode(code string) string { func formatParamCode(code string) string {
return formatCode(ToSnake(code)) snake := ToSnake(code)
} if snake == "" {
func formatCode(code string) string {
if code == "" {
return "" return ""
} }
if len(code) <= 40 { return "**`" + snake + "`**"
return "<strong><code class=\"code-no-wrap\">" + code + "</code></strong>"
}
out := []string{}
prev := rune(0)
for _, ch := range code {
if ch == '_' {
out = append(out, "_<wbr>")
prev = ch
continue
}
if prev != 0 && (unicodeIsLower(prev) || unicodeIsDigit(prev)) && unicodeIsUpper(ch) {
out = append(out, "<wbr>")
}
out = append(out, string(ch))
prev = ch
}
return "<strong><code class=\"code-wrap\">" + strings.Join(out, "") + "</code></strong>"
} }
// ToSnake конвертирует CamelCase → snake_case. // ToSnake конвертирует CamelCase → snake_case.
@@ -933,10 +914,6 @@ func ToSnake(value string) string {
return strings.Trim(string(out), "_") return strings.Trim(string(out), "_")
} }
func unicodeIsLower(r rune) bool { return r >= 'a' && r <= 'z' }
func unicodeIsUpper(r rune) bool { return r >= 'A' && r <= 'Z' }
func unicodeIsDigit(r rune) bool { return r >= '0' && r <= '9' }
func stripHTML(value string) string { func stripHTML(value string) string {
if value == "" { if value == "" {
return "" return ""
@@ -1026,23 +1003,21 @@ func renderNestedParams(p types.ParamSpec) string {
label += " (map-fixed)" label += " (map-fixed)"
} }
b.WriteString(fmt.Sprintf("\n### %s\n\n", label)) b.WriteString(fmt.Sprintf("\n### %s\n\n", label))
b.WriteString("<table class=\"resource-table resource-table-compact resource-table-nested\">\n") b.WriteString("| Code | Type | Required | Default | Description | Constraints |\n")
b.WriteString("<thead><tr><th>Code</th><th>Type</th><th>Required</th><th>Default</th><th>Description</th><th>Constraints</th></tr></thead>\n<tbody>\n") b.WriteString("|------|------|----------|---------|-------------|-------------|\n")
for _, sp := range p.SubParams { for _, sp := range p.SubParams {
req := "no" req := "no"
if sp.Required { if sp.Required {
req = "**yes**" req = "**yes**"
} }
b.WriteString("<tr>") code := formatParamCode(sp.Code)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatParamCode(sp.Code))) dtype := formatTypeCell(sp)
b.WriteString(fmt.Sprintf("<td>%s</td>", formatTypeCell(sp))) def := defaultCell(sp.Default)
b.WriteString(fmt.Sprintf("<td>%s</td>", req)) desc := escapeText(pickTextTable(sp))
b.WriteString(fmt.Sprintf("<td>%s</td>", defaultCell(sp.Default))) constr := escapeText(collectConstraints(sp))
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(pickTextTable(sp)))) b.WriteString(fmt.Sprintf("| %s | %s | %s | %s | %s | %s |\n", code, dtype, req, def, desc, constr))
b.WriteString(fmt.Sprintf("<td>%s</td>", escapeText(collectConstraints(sp))))
b.WriteString("</tr>\n")
} }
b.WriteString("</tbody></table>\n") b.WriteString("\n")
return b.String() return b.String()
} }