From ee5db187c064b9e2fbb3e776c1ab7bc6085410d9 Mon Sep 17 00:00:00 2001 From: Ilya Kuznetsov Date: Fri, 10 Jan 2025 18:33:58 +0100 Subject: [PATCH] fix: Move logic to separate fiels --- bundle/internal/docs/markdown.go | 115 ++++++++++++++ bundle/internal/docs/{docs.go => nodes.go} | 174 --------------------- bundle/internal/docs/refs.go | 71 +++++++++ 3 files changed, 186 insertions(+), 174 deletions(-) create mode 100644 bundle/internal/docs/markdown.go rename bundle/internal/docs/{docs.go => nodes.go} (50%) create mode 100644 bundle/internal/docs/refs.go diff --git a/bundle/internal/docs/markdown.go b/bundle/internal/docs/markdown.go new file mode 100644 index 000000000..3bb38ab43 --- /dev/null +++ b/bundle/internal/docs/markdown.go @@ -0,0 +1,115 @@ +package main + +import ( + "fmt" + "log" + "os" + "strings" + + md "github.com/nao1215/markdown" +) + +func buildMarkdown(nodes []rootNode, outputFile, header string) error { + f, err := os.Create(outputFile) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + m := md.NewMarkdown(f) + m = m.PlainText(header) + for _, node := range nodes { + m = m.LF() + if node.TopLevel { + m = m.H2(node.Title) + } else { + m = m.H3(node.Title) + } + m = m.LF() + + if node.Type != "" { + m = m.PlainText(fmt.Sprintf("**`Type: %s`**", node.Type)) + m = m.LF() + } + m = m.PlainText(node.Description) + m = m.LF() + + if len(node.ObjectKeyAttributes) > 0 { + n := removePluralForm(node.Title) + m = m.CodeBlocks("yaml", fmt.Sprintf("%ss:\n <%s-name>:\n <%s-field-name>: <%s-field-value>", n, n, n, n)) + m = m.LF() + m = buildAttributeTable(m, node.ObjectKeyAttributes) + } else if len(node.ArrayItemAttributes) > 0 { + m = m.LF() + m = buildAttributeTable(m, node.ArrayItemAttributes) + } else if len(node.Attributes) > 0 { + m = m.LF() + m = buildAttributeTable(m, node.Attributes) + } + + if node.Example != "" { + m = m.LF() + m = m.PlainText("**Example**") + m = m.LF() + m = m.PlainText(node.Example) + } + } + + err = m.Build() + if err != nil { + log.Fatal(err) + } + + return nil +} + +// Build a custom table which we use in Databricks website +func buildCustomAttributeTable(m *md.Markdown, attributes []attributeNode) *md.Markdown { + m = m.LF() + m = m.PlainText(".. list-table::") + m = m.PlainText(" :header-rows: 1") + m = m.LF() + + m = m.PlainText(" * - Key") + m = m.PlainText(" - Type") + m = m.PlainText(" - Description") + m = m.LF() + + for _, a := range attributes { + m = m.PlainText(" * - " + fmt.Sprintf("`%s`", a.Title)) + m = m.PlainText(" - " + a.Type) + m = m.PlainText(" - " + formatDescription(a)) + m = m.LF() + } + return m +} + +func buildAttributeTable(m *md.Markdown, attributes []attributeNode) *md.Markdown { + return buildCustomAttributeTable(m, attributes) + + // Rows below are useful for debugging since it renders the table in a regular markdown format + + // rows := [][]string{} + // for _, n := range attributes { + // rows = append(rows, []string{fmt.Sprintf("`%s`", n.Title), n.Type, formatDescription(n.Description)}) + // } + // m = m.CustomTable(md.TableSet{ + // Header: []string{"Key", "Type", "Description"}, + // Rows: rows, + // }, md.TableOptions{AutoWrapText: false, AutoFormatHeaders: false}) + + // return m +} + +func formatDescription(a attributeNode) string { + s := strings.ReplaceAll(a.Description, "\n", " ") + if a.Reference != "" { + if strings.HasSuffix(s, ".") { + s += " " + } else if s != "" { + s += ". " + } + s += fmt.Sprintf("See %s.", md.Link("_", "#"+a.Reference)) + } + return s +} diff --git a/bundle/internal/docs/docs.go b/bundle/internal/docs/nodes.go similarity index 50% rename from bundle/internal/docs/docs.go rename to bundle/internal/docs/nodes.go index de32c118f..14426f8b8 100644 --- a/bundle/internal/docs/docs.go +++ b/bundle/internal/docs/nodes.go @@ -1,15 +1,10 @@ package main import ( - "fmt" - "log" - "os" "sort" "strings" "github.com/databricks/cli/libs/jsonschema" - - md "github.com/nao1215/markdown" ) type rootNode struct { @@ -84,7 +79,6 @@ func getNodes(s jsonschema.Schema, refs map[string]jsonschema.Schema, customFiel if v.Items != nil { arrayItemType := resolveRefs(v.Items, refs) node.ArrayItemAttributes = getAttributes(arrayItemType.Properties, refs, k) - // rootProps = append(rootProps, extractNodes(k, arrayItemType.Properties, refs, customFields)...) } isEmpty := len(node.Attributes) == 0 && len(node.ObjectKeyAttributes) == 0 && len(node.ArrayItemAttributes) == 0 @@ -100,60 +94,6 @@ func getNodes(s jsonschema.Schema, refs map[string]jsonschema.Schema, customFiel return nodes } -func buildMarkdown(nodes []rootNode, outputFile, header string) error { - f, err := os.Create(outputFile) - if err != nil { - log.Fatal(err) - } - defer f.Close() - - m := md.NewMarkdown(f) - m = m.PlainText(header) - for _, node := range nodes { - m = m.LF() - if node.TopLevel { - m = m.H2(node.Title) - } else { - m = m.H3(node.Title) - } - m = m.LF() - - if node.Type != "" { - m = m.PlainText(fmt.Sprintf("**`Type: %s`**", node.Type)) - m = m.LF() - } - m = m.PlainText(node.Description) - m = m.LF() - - if len(node.ObjectKeyAttributes) > 0 { - n := removePluralForm(node.Title) - m = m.CodeBlocks("yaml", fmt.Sprintf("%ss:\n <%s-name>:\n <%s-field-name>: <%s-field-value>", n, n, n, n)) - m = m.LF() - m = buildAttributeTable(m, node.ObjectKeyAttributes) - } else if len(node.ArrayItemAttributes) > 0 { - m = m.LF() - m = buildAttributeTable(m, node.ArrayItemAttributes) - } else if len(node.Attributes) > 0 { - m = m.LF() - m = buildAttributeTable(m, node.Attributes) - } - - if node.Example != "" { - m = m.LF() - m = m.PlainText("**Example**") - m = m.LF() - m = m.PlainText(node.Example) - } - } - - err = m.Build() - if err != nil { - log.Fatal(err) - } - - return nil -} - func removePluralForm(s string) string { if strings.HasSuffix(s, "s") { return strings.TrimSuffix(s, "s") @@ -161,57 +101,6 @@ func removePluralForm(s string) string { return s } -func buildAttributeTable(m *md.Markdown, attributes []attributeNode) *md.Markdown { - return buildCustomAttributeTable(m, attributes) - - // Rows below are useful for debugging since it renders the table in a regular markdown format - - // rows := [][]string{} - // for _, n := range attributes { - // rows = append(rows, []string{fmt.Sprintf("`%s`", n.Title), n.Type, formatDescription(n.Description)}) - // } - // m = m.CustomTable(md.TableSet{ - // Header: []string{"Key", "Type", "Description"}, - // Rows: rows, - // }, md.TableOptions{AutoWrapText: false, AutoFormatHeaders: false}) - - // return m -} - -func formatDescription(a attributeNode) string { - s := strings.ReplaceAll(a.Description, "\n", " ") - if a.Reference != "" { - if strings.HasSuffix(s, ".") { - s += " " - } else if s != "" { - s += ". " - } - s += fmt.Sprintf("See %s.", md.Link("_", "#"+a.Reference)) - } - return s -} - -// Build a custom table which we use in Databricks website -func buildCustomAttributeTable(m *md.Markdown, attributes []attributeNode) *md.Markdown { - m = m.LF() - m = m.PlainText(".. list-table::") - m = m.PlainText(" :header-rows: 1") - m = m.LF() - - m = m.PlainText(" * - Key") - m = m.PlainText(" - Type") - m = m.PlainText(" - Description") - m = m.LF() - - for _, a := range attributes { - m = m.PlainText(" * - " + fmt.Sprintf("`%s`", a.Title)) - m = m.PlainText(" - " + a.Type) - m = m.PlainText(" - " + formatDescription(a)) - m = m.LF() - } - return m -} - func getHumanReadableType(t jsonschema.Type) string { typesMapping := map[string]string{ "string": "String", @@ -248,35 +137,6 @@ func getAttributes(props map[string]*jsonschema.Schema, refs map[string]jsonsche return attributes } -func isReferenceType(v *jsonschema.Schema, refs map[string]jsonschema.Schema) bool { - if len(v.Properties) > 0 { - return true - } - if v.Items != nil { - items := resolveRefs(v.Items, refs) - if items != nil && items.Type == "object" { - return true - } - } - props := resolveAdditionaProperties(v, refs) - if props != nil && props.Type == "object" { - return true - } - - return false -} - -func resolveAdditionaProperties(v *jsonschema.Schema, refs map[string]jsonschema.Schema) *jsonschema.Schema { - if v.AdditionalProperties == nil { - return nil - } - additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema) - if !ok { - return nil - } - return resolveRefs(additionalProps, refs) -} - func getDescription(s *jsonschema.Schema, allowMarkdown bool) string { if allowMarkdown && s.MarkdownDescription != "" { return s.MarkdownDescription @@ -284,40 +144,6 @@ func getDescription(s *jsonschema.Schema, allowMarkdown bool) string { return s.Description } -func resolveRefs(s *jsonschema.Schema, schemas map[string]jsonschema.Schema) *jsonschema.Schema { - node := s - - description := s.Description - markdownDescription := s.MarkdownDescription - examples := s.Examples - - for node.Reference != nil { - ref := strings.TrimPrefix(*node.Reference, "#/$defs/") - newNode, ok := schemas[ref] - if !ok { - log.Printf("schema %s not found", ref) - } - - if description == "" { - description = newNode.Description - } - if markdownDescription == "" { - markdownDescription = newNode.MarkdownDescription - } - if len(examples) == 0 { - examples = newNode.Examples - } - - node = &newNode - } - - node.Description = description - node.MarkdownDescription = markdownDescription - node.Examples = examples - - return node -} - func shouldExtract(ref string, customFields map[string]bool) bool { if i := strings.Index(ref, "github.com"); i >= 0 { ref = ref[i:] diff --git a/bundle/internal/docs/refs.go b/bundle/internal/docs/refs.go new file mode 100644 index 000000000..520a6e2c5 --- /dev/null +++ b/bundle/internal/docs/refs.go @@ -0,0 +1,71 @@ +package main + +import ( + "log" + "strings" + + "github.com/databricks/cli/libs/jsonschema" +) + +func isReferenceType(v *jsonschema.Schema, refs map[string]jsonschema.Schema) bool { + if len(v.Properties) > 0 { + return true + } + if v.Items != nil { + items := resolveRefs(v.Items, refs) + if items != nil && items.Type == "object" { + return true + } + } + props := resolveAdditionaProperties(v, refs) + if props != nil && props.Type == "object" { + return true + } + + return false +} + +func resolveAdditionaProperties(v *jsonschema.Schema, refs map[string]jsonschema.Schema) *jsonschema.Schema { + if v.AdditionalProperties == nil { + return nil + } + additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema) + if !ok { + return nil + } + return resolveRefs(additionalProps, refs) +} + +func resolveRefs(s *jsonschema.Schema, schemas map[string]jsonschema.Schema) *jsonschema.Schema { + node := s + + description := s.Description + markdownDescription := s.MarkdownDescription + examples := s.Examples + + for node.Reference != nil { + ref := strings.TrimPrefix(*node.Reference, "#/$defs/") + newNode, ok := schemas[ref] + if !ok { + log.Printf("schema %s not found", ref) + } + + if description == "" { + description = newNode.Description + } + if markdownDescription == "" { + markdownDescription = newNode.MarkdownDescription + } + if len(examples) == 0 { + examples = newNode.Examples + } + + node = &newNode + } + + node.Description = description + node.MarkdownDescription = markdownDescription + node.Examples = examples + + return node +}