Skip to content

Commit

Permalink
feat: allow generating of specific docs files only (#577)
Browse files Browse the repository at this point in the history
  • Loading branch information
jodlajodla committed Jan 18, 2022
1 parent 8ffc6c2 commit 97ea98e
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 24 deletions.
20 changes: 16 additions & 4 deletions README.md
Expand Up @@ -41,6 +41,7 @@ Swag converts Go annotations to Swagger Documentation 2.0. We've created a varie
- [Rename model to display](#rename-model-to-display)
- [How to use security annotations](#how-to-use-security-annotations)
- [Add a description for enum items](#add-a-description-for-enum-items)
- [Generate only specific docs file types](#generate-only-specific-docs-file-types)
- [About the Project](#about-the-project)

## Getting started
Expand Down Expand Up @@ -86,18 +87,20 @@ USAGE:

OPTIONS:
--generalInfo value, -g value Go file path in which 'swagger general API Info' is written (default: "main.go")
--dir value, -d value Directory you want to parse (default: "./")
--dir value, -d value Directories you want to parse,comma separated and general-info file must be in the first one (default: "./")
--exclude value Exclude directories and files when searching, comma separated
--propertyStrategy value, -p value Property Naming Strategy like snakecase,camelcase,pascalcase (default: "camelcase")
--output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and doc.go) (default: "./docs")
--output value, -o value Output directory for all the generated files(swagger.json, swagger.yaml and docs.go) (default: "./docs")
--outputTypes value, --ot value Output types of generated files (docs.go, swagger.json, swagger.yaml) like go,json,yaml (default: "go,json,yaml")
--parseVendor Parse go files in 'vendor' folder, disabled by default (default: false)
--parseDependency Parse go files in outside dependency folder, disabled by default (default: false)
--parseDependency, --pd Parse go files inside dependency folder, disabled by default (default: false)
--markdownFiles value, --md value Parse folder containing markdown files to use as description, disabled by default
--codeExampleFiles value, --cef value Parse folder containing code example files to use for the x-codeSamples extension, disabled by default
--parseInternal Parse go files in internal packages, disabled by default (default: false)
--generatedTime Generate timestamp at the top of docs.go, disabled by default (default: false)
--parseDepth value Dependency parse depth (default: 100)
--instanceName value Set the swagger document instance name (default: "swagger")
--instanceName value This parameter can be used to name different swagger document instances. It is optional.
--overridesFile value File to read global type overrides from. (default: ".swaggo")
--help, -h show help (default: false)
```

Expand Down Expand Up @@ -797,6 +800,15 @@ type Example struct {
}
```

### Generate only specific docs file types

By default `swag` command generates Swagger specification in three different files/file types:
- docs.go
- swagger.json
- swagger.yaml

If you would like to limit a set of file types which should be generated you can use `--outputTypes` (short `-ot`) flag. Default value is `go,json,yaml` - output types separated with comma. To limit output only to `go` and `yaml` files, you would write `go,yaml`. With complete command that would be `swag init --outputTypes go,yaml`.

## About the Project
This project was inspired by [yvasiyarov/swagger](https://github.com/yvasiyarov/swagger) but we simplified the usage and added support a variety of [web frameworks](#supported-web-frameworks). Gopher image source is [tenntenn/gopher-stickers](https://github.com/tenntenn/gopher-stickers). It has licenses [creative commons licensing](http://creativecommons.org/licenses/by/3.0/deed.en).
## Contributors
Expand Down
16 changes: 15 additions & 1 deletion cmd/swag/main.go
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"
"os"
"strings"

"github.com/urfave/cli/v2"

Expand All @@ -18,6 +19,7 @@ const (
generalInfoFlag = "generalInfo"
propertyStrategyFlag = "propertyStrategy"
outputFlag = "output"
outputTypesFlag = "outputTypes"
parseVendorFlag = "parseVendor"
parseDependencyFlag = "parseDependency"
markdownFilesFlag = "markdownFiles"
Expand Down Expand Up @@ -56,7 +58,13 @@ var initFlags = []cli.Flag{
Name: outputFlag,
Aliases: []string{"o"},
Value: "./docs",
Usage: "Output directory for all the generated files(swagger.json, swagger.yaml and doc.go)",
Usage: "Output directory for all the generated files(swagger.json, swagger.yaml and docs.go)",
},
&cli.StringFlag{
Name: outputTypesFlag,
Aliases: []string{"ot"},
Value: "go,json,yaml",
Usage: "Output types of generated files (docs.go, swagger.json, swagger.yaml) like go,json,yaml",
},
&cli.BoolFlag{
Name: parseVendorFlag,
Expand Down Expand Up @@ -113,12 +121,18 @@ func initAction(c *cli.Context) error {
return fmt.Errorf("not supported %s propertyStrategy", strategy)
}

outputTypes := strings.Split(c.String(outputTypesFlag), ",")
if len(outputTypes) == 0 {
return fmt.Errorf("no output types specified")
}

return gen.New().Build(&gen.Config{
SearchDir: c.String(searchDirFlag),
Excludes: c.String(excludeFlag),
MainAPIFile: c.String(generalInfoFlag),
PropNamingStrategy: strategy,
OutputDir: c.String(outputFlag),
OutputTypes: outputTypes,
ParseVendor: c.Bool(parseVendorFlag),
ParseDependency: c.Bool(parseDependencyFlag),
MarkdownFilesDir: c.String(markdownFilesFlag),
Expand Down
88 changes: 69 additions & 19 deletions gen/gen.go
Expand Up @@ -9,6 +9,7 @@ import (
"io"
"log"
"os"
"path"
"path/filepath"
"strings"
"text/template"
Expand All @@ -24,20 +25,36 @@ var open = os.Open
// DefaultOverridesFile is the location swaggo will look for type overrides.
const DefaultOverridesFile = ".swaggo"

type genTypeWriter func(*Config, *spec.Swagger) error

// Gen presents a generate tool for swag.
type Gen struct {
jsonIndent func(data interface{}) ([]byte, error)
jsonToYAML func(data []byte) ([]byte, error)
json func(data interface{}) ([]byte, error)
jsonIndent func(data interface{}) ([]byte, error)
jsonToYAML func(data []byte) ([]byte, error)
outputTypeMap map[string]genTypeWriter
}

// New creates a new Gen.
func New() *Gen {
return &Gen{
gen := &Gen{
json: func(data interface{}) ([]byte, error) {
return json.Marshal(data)
},
jsonIndent: func(data interface{}) ([]byte, error) {
return json.MarshalIndent(data, "", " ")
},
jsonToYAML: yaml.JSONToYAML,
}

gen.outputTypeMap = map[string]genTypeWriter{
"go": gen.writeDocSwagger,
"json": gen.writeJSONSwagger,
"yaml": gen.writeYAMLSwagger,
"yml": gen.writeYAMLSwagger,
}

return gen
}

// Config presents Gen configurations.
Expand All @@ -51,6 +68,9 @@ type Config struct {
// OutputDir represents the output directory for all the generated files
OutputDir string

// OutputTypes define types of files which should be generated
OutputTypes []string

// MainAPIFile the Go file path in which 'swagger general API Info' is written
MainAPIFile string

Expand Down Expand Up @@ -137,55 +157,85 @@ func (g *Gen) Build(config *Config) error {
}
swagger := p.GetSwagger()

b, err := g.jsonIndent(swagger)
if err != nil {
if err := os.MkdirAll(config.OutputDir, os.ModePerm); err != nil {
return err
}

if err := os.MkdirAll(config.OutputDir, os.ModePerm); err != nil {
return err
for _, outputType := range config.OutputTypes {
outputType = strings.ToLower(strings.TrimSpace(outputType))
if typeWriter, ok := g.outputTypeMap[outputType]; ok {
if err := typeWriter(config, swagger); err != nil {
return err
}
} else {
log.Printf("output type '%s' not supported", outputType)
}
}

return nil
}

func (g *Gen) writeDocSwagger(config *Config, swagger *spec.Swagger) error {
docFileName := path.Join(config.OutputDir, "docs.go")

absOutputDir, err := filepath.Abs(config.OutputDir)
if err != nil {
return err
}
packageName := filepath.Base(absOutputDir)
docFileName := filepath.Join(config.OutputDir, "docs.go")
jsonFileName := filepath.Join(config.OutputDir, "swagger.json")
yamlFileName := filepath.Join(config.OutputDir, "swagger.yaml")

docs, err := os.Create(docFileName)
if err != nil {
return err
}
defer docs.Close()

err = g.writeFile(b, jsonFileName)
// Write doc
err = g.writeGoDoc(packageName, docs, swagger, config)
if err != nil {
return err
}

y, err := g.jsonToYAML(b)
log.Printf("create docs.go at %+v", docFileName)
return nil
}

func (g *Gen) writeJSONSwagger(config *Config, swagger *spec.Swagger) error {
jsonFileName := path.Join(config.OutputDir, "swagger.json")

b, err := g.jsonIndent(swagger)
if err != nil {
return fmt.Errorf("cannot convert json to yaml error: %s", err)
return err
}

err = g.writeFile(y, yamlFileName)
err = g.writeFile(b, jsonFileName)
if err != nil {
return err
}

// Write doc
err = g.writeGoDoc(packageName, docs, swagger, config)
log.Printf("create swagger.json at %+v", jsonFileName)
return nil
}

func (g *Gen) writeYAMLSwagger(config *Config, swagger *spec.Swagger) error {
yamlFileName := path.Join(config.OutputDir, "swagger.yaml")

b, err := g.json(swagger)
if err != nil {
return err
}

log.Printf("create docs.go at %+v", docFileName)
log.Printf("create swagger.json at %+v", jsonFileName)
log.Printf("create swagger.yaml at %+v", yamlFileName)
y, err := g.jsonToYAML(b)
if err != nil {
return fmt.Errorf("cannot covert json to yaml error: %s", err)
}

err = g.writeFile(y, yamlFileName)
if err != nil {
return err
}

log.Printf("create swagger.yaml at %+v", yamlFileName)
return nil
}

Expand Down

0 comments on commit 97ea98e

Please sign in to comment.