Skip to content

Commit

Permalink
feat: doc gen: support generate package doc in a single page; add ref…
Browse files Browse the repository at this point in the history
… link (#173)

* ref to schema id

Signed-off-by: xiarui.xr <xiarui.xr@antgroup.com>

* support reference link between schemas; generate doc in single package

Signed-off-by: xiarui.xr <xiarui.xr@antgroup.com>

---------

Signed-off-by: xiarui.xr <xiarui.xr@antgroup.com>
  • Loading branch information
amyXia1994 authored Oct 27, 2023
1 parent e3cd746 commit cbfc2a6
Show file tree
Hide file tree
Showing 22 changed files with 152 additions and 490 deletions.
83 changes: 35 additions & 48 deletions pkg/tools/gen/gendoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ var schemaDocTmpl string
//go:embed templates/doc/packageDoc.gotmpl
var packageDocTmpl string

//go:embed templates/doc/schemaListDoc.gotmpl
var schemaListDocTmpl string

const (
schemaDocTmplFile = "schemaDoc.gotmpl"
packageDocTmplFile = "packageDoc.gotmpl"
schemaDocTmplFile = "schemaDoc.gotmpl"
packageDocTmplFile = "packageDoc.gotmpl"
schemaListDocTmplFile = "schemaListDoc.gotmpl"
)

// GenContext defines the context during the generation
Expand All @@ -40,6 +44,8 @@ type GenContext struct {
SchemaDocTmpl string
// PackageDocTmpl defines the content of the packageDoc template
PackageDocTmpl string
// SchemaListDocTmpl defines the content of the schemaListDoc template
SchemaListDocTmpl string
// Template is the doc render template
Template *template.Template
}
Expand Down Expand Up @@ -169,7 +175,7 @@ func funcMap() template.FuncMap {
return false
},
"kclType": func(tpe KclOpenAPIType) string {
return tpe.GetKclTypeName(false)
return tpe.GetKclTypeName(false, true)
},
"fullTypeName": func(tpe KclOpenAPIType) string {
if tpe.KclExtensions.XKclModelType.Import.Package != "" {
Expand All @@ -192,50 +198,31 @@ func funcMap() template.FuncMap {
return filepath.Join(tpe.GetSchemaPkgDir(""), tpe.KclExtensions.XKclModelType.Import.Alias)
},
"indexContent": func(pkg *KclPackage) string {
return pkg.getIndexContent(0, " ", "", false)
},
"indexContentIgnoreDirPath": func(pkg *KclPackage) string {
return pkg.getIndexContent(0, " ", "", true)
return pkg.getIndexContent(0, " ")
},
}
}

func (pkg *KclPackage) getPackageIndexContent(level int, indentation string, pkgPath string, ignoreDir bool) string {
currentPkgPath := filepath.Join(pkgPath, pkg.Name)
currentDocPath := pkg.Name
if !ignoreDir {
// get the full directory path
currentDocPath = filepath.Join(currentPkgPath, fmt.Sprintf("%s.md", pkg.Name))
}
return fmt.Sprintf(`%s- [%s](%s)
%s`, strings.Repeat(indentation, level), pkg.Name, currentDocPath, pkg.getIndexContent(level+1, indentation, currentPkgPath, ignoreDir))
func (pkg *KclPackage) getPackageIndexContent(level int, indentation string) string {
return fmt.Sprintf(`%s- %s
%s`, strings.Repeat(indentation, level), pkg.Name, pkg.getIndexContent(level+1, indentation))
}

func (tpe *KclOpenAPIType) getSchemaIndexContent(level int, indentation string, pkgPath string, pkgName string, ignoreDir bool) string {
docPath := pkgName
if !ignoreDir {
// get the full directory path
docPath = filepath.Join(pkgPath, fmt.Sprintf("%s.md", pkgName))
}
if level == 0 {
// the schema is defined in current package
docPath = ""
}

return fmt.Sprintf(`%s- [%s](%s#%s)
`, strings.Repeat(indentation, level), tpe.KclExtensions.XKclModelType.Type, docPath, strings.ToLower(tpe.KclExtensions.XKclModelType.Type))
func (tpe *KclOpenAPIType) getSchemaIndexContent(level int, indentation string) string {
return fmt.Sprintf(`%s- [%s](#%s)
`, strings.Repeat(indentation, level), tpe.KclExtensions.XKclModelType.Type, strings.ToLower(tpe.KclExtensions.XKclModelType.Type))
}

func (pkg *KclPackage) getIndexContent(level int, indentation string, pkgPath string, ignoreDir bool) string {
func (pkg *KclPackage) getIndexContent(level int, indentation string) string {
var content string
if len(pkg.SchemaList) > 0 {
for _, sch := range pkg.SchemaList {
content += sch.getSchemaIndexContent(level, indentation, pkgPath, pkg.Name, ignoreDir)
content += sch.getSchemaIndexContent(level, indentation)
}
}
if len(pkg.SubPackageList) > 0 {
for _, pkg := range pkg.SubPackageList {
content += pkg.getPackageIndexContent(level, indentation, pkgPath, ignoreDir)
content += pkg.getPackageIndexContent(level, indentation)
}
}
return content
Expand All @@ -247,7 +234,7 @@ func (g *GenContext) renderPackage(pkg *KclPackage, parentDir string) error {
pkgName = "main"
}
fmt.Println(fmt.Sprintf("generating doc for package %s", pkgName))
indexFileName := fmt.Sprintf("%s.%s", pkgName, g.Format)
docFileName := fmt.Sprintf("%s.%s", pkgName, g.Format)
var contentBuf bytes.Buffer
err := g.Template.ExecuteTemplate(&contentBuf, "packageDoc", struct {
EscapeHtml bool
Expand All @@ -260,22 +247,9 @@ func (g *GenContext) renderPackage(pkg *KclPackage, parentDir string) error {
return fmt.Errorf("failed to render package %s with template, err: %s", pkg.Name, err)
}
// write content to file
err = os.WriteFile(filepath.Join(parentDir, indexFileName), contentBuf.Bytes(), 0644)
err = os.WriteFile(filepath.Join(parentDir, docFileName), contentBuf.Bytes(), 0644)
if err != nil {
return fmt.Errorf("failed to write file %s in %s: %v", indexFileName, parentDir, err)
}

for _, sub := range pkg.SubPackageList {
pkgDir := GetPkgDir(parentDir, sub.Name)
//fmt.Println(fmt.Sprintf("creating directory: %s", pkgDir))
err := os.MkdirAll(pkgDir, 0755)
if err != nil {
return fmt.Errorf("failed to create docs/%s directory under the target directory: %s", pkgDir, err)
}
err = g.renderPackage(sub, pkgDir)
if err != nil {
return err
}
return fmt.Errorf("failed to write file %s in %s: %v", docFileName, parentDir, err)
}
return nil
}
Expand Down Expand Up @@ -308,6 +282,7 @@ func (opts *GenOpts) ValidateComplete() (*GenContext, error) {
// --- template directory ---
g.SchemaDocTmpl = schemaDocTmpl
g.PackageDocTmpl = packageDocTmpl
g.SchemaListDocTmpl = schemaListDocTmpl
if opts.TemplateDir != "" {
tmplAbsPath := filepath.Join(g.PackagePath, opts.TemplateDir)
templatesDirInfo, err := os.Stat(tmplAbsPath)
Expand Down Expand Up @@ -343,6 +318,14 @@ func (opts *GenOpts) ValidateComplete() (*GenContext, error) {
}
g.PackageDocTmpl = string(content)
return nil
case schemaListDocTmplFile:
// use custom schema list Doc Template file
content, err := os.ReadFile(path)
if err != nil {
return err
}
g.SchemaListDocTmpl = string(content)
return nil
default:
return fmt.Errorf("unexpected template file: %s", path)
}
Expand All @@ -361,6 +344,10 @@ func (opts *GenOpts) ValidateComplete() (*GenContext, error) {
if err != nil {
return nil, err
}
_, err = g.Template.Parse(g.SchemaListDocTmpl)
if err != nil {
return nil, err
}

// --- target ---
if opts.Target == "" {
Expand Down
46 changes: 12 additions & 34 deletions pkg/tools/gen/gendoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ import (
assert2 "github.com/stretchr/testify/assert"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
)

func TestIndexContent(t *testing.T) {
if runtime.GOOS == "windows" {
return
}
rootPkg := KclPackage{
Name: "test",
SubPackageList: []*KclPackage{
Expand Down Expand Up @@ -57,33 +53,21 @@ func TestIndexContent(t *testing.T) {
},
}
tCases := []struct {
root KclPackage
ignoreDir bool
expect string
root KclPackage
expect string
}{
{
root: rootPkg,
ignoreDir: false,
expect: `- [A](#a)
- [sub1](sub1/sub1.md)
- [B](sub1/sub1.md#b)
- [sub2](sub1/sub2/sub2.md)
- [C](sub1/sub2/sub2.md#c)
`,
},
{
root: rootPkg,
ignoreDir: true,
root: rootPkg,
expect: `- [A](#a)
- [sub1](sub1)
- [B](sub1#b)
- [sub2](sub2)
- [C](sub2#c)
- sub1
- [B](#b)
- sub2
- [C](#c)
`,
},
}
for _, tCase := range tCases {
got := tCase.root.getIndexContent(0, " ", "", tCase.ignoreDir)
got := tCase.root.getIndexContent(0, " ")
assert2.Equal(t, tCase.expect, got)
}
}
Expand Down Expand Up @@ -138,18 +122,12 @@ func initTestCases(t *testing.T) []*TestCase {

for i, p := range sourcePkgs {
packageDir := filepath.Join(cwd, testdataDir, p)
var resultDir string
if runtime.GOOS == "windows" {
resultDir = filepath.Join(packageDir, "windows")
} else {
resultDir = filepath.Join(packageDir, "unixlike")
}
tcases[i] = &TestCase{
PackagePath: packageDir,
ExpectMd: filepath.Join(resultDir, "md"),
ExpectHtml: filepath.Join(resultDir, "html"),
GotMd: filepath.Join(resultDir, "md_got"),
GotHtml: filepath.Join(resultDir, "html_got"),
ExpectMd: filepath.Join(packageDir, "md"),
ExpectHtml: filepath.Join(packageDir, "html"),
GotMd: filepath.Join(packageDir, "md_got"),
GotHtml: filepath.Join(packageDir, "html_got"),
}
}
return tcases
Expand Down
25 changes: 17 additions & 8 deletions pkg/tools/gen/genopenapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,15 @@ type XKclDecorators struct {
}

// GetKclTypeName get the string representation of a KclOpenAPIType
func (tpe *KclOpenAPIType) GetKclTypeName(omitAny bool) string {
func (tpe *KclOpenAPIType) GetKclTypeName(omitAny bool, addLink bool) string {
if tpe.Ref != "" {
schemaId := strings.TrimPrefix(tpe.Ref, oaiV2Ref)
return schemaId[strings.LastIndex(schemaId, ".")+1:]
schemaId := Ref2SchemaId(tpe.Ref)
schemaName := schemaId[strings.LastIndex(schemaId, ".")+1:]
if addLink {
return fmt.Sprintf("[%s](#%s)", schemaName, strings.ToLower(schemaName))
} else {
return schemaName
}
}
switch tpe.Type {
case String:
Expand Down Expand Up @@ -214,20 +219,20 @@ func (tpe *KclOpenAPIType) GetKclTypeName(omitAny bool) string {
}
return typBool
case Array:
return fmt.Sprintf("[%s]", tpe.Items.GetKclTypeName(true))
return fmt.Sprintf("[%s]", tpe.Items.GetKclTypeName(true, addLink))
case Object:
if tpe.AdditionalProperties != nil {
// dict type
if tpe.KclExtensions.XKclDictKeyType.isAnyType() && tpe.AdditionalProperties.isAnyType() {
return "{}"
}
return fmt.Sprintf("{%s:%s}", tpe.KclExtensions.XKclDictKeyType.GetKclTypeName(true), tpe.AdditionalProperties.GetKclTypeName(true))
return fmt.Sprintf("{%s:%s}", tpe.KclExtensions.XKclDictKeyType.GetKclTypeName(true, addLink), tpe.AdditionalProperties.GetKclTypeName(true, addLink))
}
if tpe.KclExtensions != nil && len(tpe.KclExtensions.XKclUnionTypes) > 0 {
// union type
tpes := make([]string, len(tpe.KclExtensions.XKclUnionTypes))
for i, unionType := range tpe.KclExtensions.XKclUnionTypes {
tpes[i] = unionType.GetKclTypeName(true)
tpes[i] = unionType.GetKclTypeName(true, addLink)
}
return strings.Join(tpes, " | ")
}
Expand Down Expand Up @@ -300,7 +305,7 @@ func GetKclOpenAPIType(pkgPath string, from *kcl.KclType, nested bool) *KclOpenA
id := SchemaId(pkgPath, from)
if nested {
// for nested type reference, just return the ref object
t.Ref = refPath(id)
t.Ref = SchemaId2Ref(id)
return &t
}
// resolve schema type
Expand Down Expand Up @@ -409,6 +414,10 @@ func SchemaId(pkgPath string, t *kcl.KclType) string {
return fmt.Sprintf("%s.%s", pkgName, t.SchemaName)
}

func refPath(id string) string {
func SchemaId2Ref(id string) string {
return fmt.Sprintf("%s%s", oaiV2Ref, id)
}

func Ref2SchemaId(ref string) string {
return strings.TrimPrefix(ref, oaiV2Ref)
}
5 changes: 2 additions & 3 deletions pkg/tools/gen/templates/doc/packageDoc.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
## Index

{{ indexContent $Data }}
{{ if $Data.SchemaList}}
{{- if or $Data.SchemaList $Data.SubPackageList}}
## Schemas

{{range $i, $schema := $Data.SchemaList }}{{template "schemaDoc" (arr $schema $EscapeHtml) }}
{{template "schemaListDoc" (arr $Data $EscapeHtml) }}
{{- end -}}
{{end -}}
<!-- Auto generated by kcl-doc tool, please do not edit. -->
{{end}}
2 changes: 1 addition & 1 deletion pkg/tools/gen/templates/doc/schemaDoc.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

{{range $name, $property := $Data.Properties}}**{{$name}}**{{if containsString $Data.Required $name }} *required*{{end}}{{if $property.ReadOnly}} *readOnly*{{end}}

`{{kclType $property}}`{{if ne $property.Description ""}}
{{kclType $property}}{{if ne $property.Description ""}}

{{escapeHtml $property.Description $EscapeHtml}}{{end}}

Expand Down
13 changes: 13 additions & 0 deletions pkg/tools/gen/templates/doc/schemaListDoc.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- define "schemaListDoc" -}}

{{- $Data := index . 0 -}}
{{- $EscapeHtml := index . 1 -}}
{{- if $Data.SchemaList }}{{range $i, $schema := $Data.SchemaList }}{{template "schemaDoc" (arr $schema $EscapeHtml) }}
{{- end -}}
{{- end -}}

{{- if $Data.SubPackageList}}{{range $i, $pkg := $Data.SubPackageList }}{{template "schemaListDoc" (arr $pkg $EscapeHtml) }}
{{- end -}}
{{- end -}}

{{- end -}}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# apps
# main

## Index

- [Deployment](#deployment)

- apps
- [Deployment](#deployment)
- core
- [PodSpec](#podspec)

## Schemas

Expand All @@ -13,10 +15,18 @@

**metadata** *required*

`str`
str

**podSpec** *required*

`any`
any

### PodSpec

#### Attributes

**image** *required*

str

<!-- Auto generated by kcl-doc tool, please do not edit. -->
18 changes: 0 additions & 18 deletions pkg/tools/gen/testdata/doc/k8s/unixlike/md/core/core.md

This file was deleted.

Loading

0 comments on commit cbfc2a6

Please sign in to comment.