Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: doc gen: support generate package doc in a single page; add ref link #173

Merged
merged 2 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading