From 0b3d671774cd2b3b94d3f362d3b8be2479619276 Mon Sep 17 00:00:00 2001 From: zeevdr Date: Thu, 11 Jun 2026 10:20:49 +0300 Subject: [PATCH] docgen: compact field metadata line and deprecation callout Replace the per-field property table with a single italic metadata line (type, format, nullable, default, read-only, write-once, sensitive, tags) and render deprecation as a blockquote callout naming the redirect target. Constraints and examples sections are unchanged. Shrinks generated docs and makes field headers scannable. Co-Authored-By: Claude Fable 5 --- sdk/tools/docgen/docgen.go | 61 +++++++++++++++++---------------- sdk/tools/docgen/docgen_test.go | 29 ++++++++++------ 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/sdk/tools/docgen/docgen.go b/sdk/tools/docgen/docgen.go index 04bedfa6..00a816e2 100644 --- a/sdk/tools/docgen/docgen.go +++ b/sdk/tools/docgen/docgen.go @@ -234,36 +234,16 @@ func writeField(b *strings.Builder, f Field, cfg *config) { fmt.Fprintf(b, "### `%s`\n\n", f.Path) } - // Property table. - fmt.Fprintln(b, "| Property | Value |") - fmt.Fprintln(b, "|----------|-------|") - fmt.Fprintf(b, "| Type | %s |\n", f.Type) - if f.Format != "" { - fmt.Fprintf(b, "| Format | %s |\n", f.Format) - } - fmt.Fprintf(b, "| Nullable | %s |\n", yesNo(f.Nullable)) - if f.Default != "" { - fmt.Fprintf(b, "| Default | `%s` |\n", f.Default) - } - if f.ReadOnly { - fmt.Fprint(b, "| Read-only | yes |\n") - } - if f.WriteOnce { - fmt.Fprint(b, "| Write-once | yes |\n") - } - if f.Sensitive { - fmt.Fprint(b, "| Sensitive | yes |\n") - } + fmt.Fprintf(b, "%s\n\n", fieldMeta(f)) + if f.Deprecated { - fmt.Fprint(b, "| Deprecated | yes |\n") if f.RedirectTo != "" { - fmt.Fprintf(b, "| Redirect | `%s` |\n", f.RedirectTo) + fmt.Fprintf(b, "> **Deprecated** — use `%s` instead.\n\n", f.RedirectTo) + } else { + fmt.Fprintln(b, "> **Deprecated.**") + fmt.Fprintln(b) } } - if len(f.Tags) > 0 { - fmt.Fprintf(b, "| Tags | %s |\n", strings.Join(f.Tags, ", ")) - } - fmt.Fprintln(b) if f.Description != "" { fmt.Fprintf(b, "%s\n\n", f.Description) @@ -339,9 +319,30 @@ func writeConstraints(b *strings.Builder, c *Constraints) { } } -func yesNo(v bool) string { - if v { - return "yes" +// fieldMeta renders a field's type and flags as a single italic line, e.g. +// "*type: `string` · format: email · default: `prod` · sensitive*". +func fieldMeta(f Field) string { + parts := []string{fmt.Sprintf("type: `%s`", f.Type)} + if f.Format != "" { + parts = append(parts, fmt.Sprintf("format: %s", f.Format)) + } + if f.Nullable { + parts = append(parts, "nullable") + } + if f.Default != "" { + parts = append(parts, fmt.Sprintf("default: `%s`", f.Default)) + } + if f.ReadOnly { + parts = append(parts, "read-only") + } + if f.WriteOnce { + parts = append(parts, "write-once") + } + if f.Sensitive { + parts = append(parts, "sensitive") + } + if len(f.Tags) > 0 { + parts = append(parts, fmt.Sprintf("tags: %s", strings.Join(f.Tags, ", "))) } - return "no" + return "*" + strings.Join(parts, " · ") + "*" } diff --git a/sdk/tools/docgen/docgen_test.go b/sdk/tools/docgen/docgen_test.go index 753632d7..03a30b27 100644 --- a/sdk/tools/docgen/docgen_test.go +++ b/sdk/tools/docgen/docgen_test.go @@ -101,8 +101,17 @@ func TestGenerate_Deprecated(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "Deprecated | yes") - assertContains(t, md, "Redirect | `new_field`") + assertContains(t, md, "> **Deprecated** — use `new_field` instead.") +} + +func TestGenerate_DeprecatedNoRedirect(t *testing.T) { + schema := Schema{ + Name: "test", + Fields: []Field{{Path: "old_field", Type: "string", Deprecated: true}}, + } + + md := Generate(schema) + assertContains(t, md, "> **Deprecated.**") } func TestGenerate_WithoutDeprecated(t *testing.T) { @@ -131,8 +140,8 @@ func TestGenerate_Nullable(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "Nullable | yes") - assertContains(t, md, "Nullable | no") + assertContains(t, md, "### `a`\n\n*type: `string` · nullable*") + assertContains(t, md, "### `b`\n\n*type: `string`*") } func TestGenerate_Default(t *testing.T) { @@ -142,7 +151,7 @@ func TestGenerate_Default(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "Default | `hello`") + assertContains(t, md, "default: `hello`") } func TestGenerate_NoPrefix(t *testing.T) { @@ -280,7 +289,7 @@ func TestGenerate_Tags(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "| Tags | billing, critical |") + assertContains(t, md, "tags: billing, critical") } func TestGenerate_Format(t *testing.T) { @@ -290,7 +299,7 @@ func TestGenerate_Format(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "| Format | email |") + assertContains(t, md, "format: email") } func TestGenerate_ReadOnlyWriteOnceSensitive(t *testing.T) { @@ -304,9 +313,9 @@ func TestGenerate_ReadOnlyWriteOnceSensitive(t *testing.T) { } md := Generate(schema) - assertContains(t, md, "| Read-only | yes |") - assertContains(t, md, "| Write-once | yes |") - assertContains(t, md, "| Sensitive | yes |") + assertContains(t, md, "*type: `string` · read-only*") + assertContains(t, md, "*type: `string` · write-once*") + assertContains(t, md, "*type: `string` · sensitive*") } func assertContains(t *testing.T, s, substr string) {