diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index d6ff20d..619ca74 100644 --- a/.github/workflows/cloc.yml +++ b/.github/workflows/cloc.yml @@ -24,7 +24,9 @@ jobs: - name: Count Lines Of Code id: loc run: | - curl -sLO https://github.com/vearutop/sccdiff/releases/download/v1.0.1/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz + curl -sLO https://github.com/vearutop/sccdiff/releases/download/v1.0.3/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz + sccdiff_hash=$(git hash-object ./sccdiff) + [ "$sccdiff_hash" == "ae8a07b687bd3dba60861584efe724351aa7ff63" ] || (echo "::error::unexpected hash for sccdiff, possible tampering: $sccdiff_hash" && exit 1) OUTPUT=$(cd pr && ../sccdiff -basedir ../base) echo "${OUTPUT}" OUTPUT="${OUTPUT//$'\n'/%0A}" diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index b4f7600..a38a33d 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -21,13 +21,13 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.19.x - uses: actions/checkout@v2 - name: golangci-lint uses: golangci/golangci-lint-action@v3.1.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.45.2 + version: v1.49.0 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/.github/workflows/gorelease.yml b/.github/workflows/gorelease.yml index 429d5ed..6267500 100644 --- a/.github/workflows/gorelease.yml +++ b/.github/workflows/gorelease.yml @@ -9,7 +9,7 @@ concurrency: cancel-in-progress: true env: - GO_VERSION: 1.18.x + GO_VERSION: 1.19.x jobs: gorelease: runs-on: ubuntu-latest @@ -35,12 +35,12 @@ jobs: with: path: | ~/go/bin/gorelease - key: ${{ runner.os }}-gorelease + key: ${{ runner.os }}-gorelease-generic - name: Gorelease id: gorelease run: | test -e ~/go/bin/gorelease || go install golang.org/x/exp/cmd/gorelease@latest - OUTPUT=$(gorelease || exit 0) + OUTPUT=$(gorelease 2>&1 || exit 0) echo "${OUTPUT}" OUTPUT="${OUTPUT//$'\n'/%0A}" echo "::set-output name=report::$OUTPUT" diff --git a/.golangci.yml b/.golangci.yml index 1e14dbd..b2476b3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -37,6 +37,12 @@ linters: - tagliatelle - errname - ireturn + - exhaustruct + - nonamedreturns + - nosnakecase + - structcheck + - varcheck + - deadcode issues: exclude-use-default: false @@ -54,5 +60,12 @@ issues: - noctx - funlen - dupl + - structcheck + - unused + - unparam + - nosnakecase path: "_test.go" + - linters: + - errcheck # Error checking omitted for brevity. + path: "example_" diff --git a/Makefile b/Makefile index cf634a0..4015c30 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -#GOLANGCI_LINT_VERSION := "v1.45.2" # Optional configuration to pinpoint golangci-lint version. +#GOLANGCI_LINT_VERSION := "v1.49.0" # Optional configuration to pinpoint golangci-lint version. # The head of Makefile determines location of dev-go to include standard targets. GO ?= go diff --git a/doc.go b/doc.go index cc35a24..63136aa 100644 --- a/doc.go +++ b/doc.go @@ -4,11 +4,11 @@ // // 1. Install tools: // -// go get -u github.com/shurcooL/vfsgen +// go get -u github.com/shurcooL/vfsgen // // 2. Generate file: // // At root folder, run command: -// go generate // +// go generate package swgui diff --git a/go.mod b/go.mod index b6ab0ab..69a9690 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/swaggest/swgui go 1.17 require ( - github.com/bool64/dev v0.2.10 + github.com/bool64/dev v0.2.20 github.com/shurcooL/httpgzip v0.0.0-20190720172056-320755c1c1b0 github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd github.com/vearutop/statigz v1.1.5 diff --git a/go.sum b/go.sum index a674249..37c7558 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/bool64/dev v0.1.41/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU= -github.com/bool64/dev v0.2.10 h1:ypAGBazcwyIy2JvIJio8V3kdqO7AgIAYvcckW54qxr4= -github.com/bool64/dev v0.2.10/go.mod h1:/csLrm+4oDSsKJRIVS0mrywAonLnYKFG8RvGT7Jh9b8= +github.com/bool64/dev v0.2.20 h1:9eIRGdcg2kQW2NGza++QbOKidNNaK+KfWuUXcZFDejE= +github.com/bool64/dev v0.2.20/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/internal/handler.go b/internal/handler.go index 414c5f5..b941dee 100644 --- a/internal/handler.go +++ b/internal/handler.go @@ -33,7 +33,7 @@ func NewHandlerWithConfig(config swgui.Config, assetsBase, faviconBase string, s panic(err) } - h.ConfigJson = template.JS(j) // nolint:gosec // Data is well formed. + h.ConfigJson = template.JS(j) //nolint:gosec // Data is well formed. h.tpl, err = template.New("index").Parse(IndexTpl(assetsBase, faviconBase, config)) if err != nil { diff --git a/internal/index.tpl.go b/internal/index.tpl.go index cc28278..7059c8c 100644 --- a/internal/index.tpl.go +++ b/internal/index.tpl.go @@ -8,7 +8,8 @@ import ( ) // IndexTpl creates page template. -// nolint:funlen // The template is long. +// +//nolint:funlen // The template is long. func IndexTpl(assetsBase, faviconBase string, cfg swgui.Config) string { settings := map[string]string{ "url": "url", @@ -21,10 +22,11 @@ func IndexTpl(assetsBase, faviconBase string, cfg swgui.Config) string { "plugins": `[ SwaggerUIBundle.plugins.DownloadUrl ]`, - "layout": `"StandaloneLayout"`, - "showExtensions": "true", - "showCommonExtensions": "true", - "validatorUrl": "null", + "layout": `"StandaloneLayout"`, + "showExtensions": "true", + "showCommonExtensions": "true", + "validatorUrl": "null", + "defaultModelsExpandDepth": "-1", // Hides schemas, override with value "1" in Config.SettingsUI to show schemas. `onComplete`: `function() { if (cfg.preAuthorizeApiKey) { for (var name in cfg.preAuthorizeApiKey) { diff --git a/swgui-server/main.go b/swgui-server/main.go deleted file mode 100644 index aa78363..0000000 --- a/swgui-server/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "net/http" - - v3 "github.com/swaggest/swgui/v3" -) - -var ( - host string - port uint - title string -) - -func main() { - flag.StringVar(&host, "host", "", "Host") - flag.UintVar(&port, "port", 8080, "Port") - flag.StringVar(&title, "title", "API Document", "Page title") - - flag.Parse() - - var h http.Handler = v3.NewHandler(title, "/swagger.json", "/") - - http.Handle("/", h) - fmt.Printf("Listening at %s:%d\n", host, port) - - err := http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil) - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/gen/gen.go b/v3/gen/gen.go index e279b90..649a8f4 100644 --- a/v3/gen/gen.go +++ b/v3/gen/gen.go @@ -1,3 +1,4 @@ +// Package main generates legacy assets. package main import ( diff --git a/v3/handler.go b/v3/handler.go index 2117ed0..d0fdefa 100644 --- a/v3/handler.go +++ b/v3/handler.go @@ -16,6 +16,25 @@ func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath) } +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // NewHandler creates HTTP handler for Swagger UI. func NewHandler(title, swaggerJSONPath string, basePath string) *Handler { return NewHandlerWithConfig(swgui.Config{ diff --git a/v3/static.go b/v3/static.go index 23dd1ed..caa7ab9 100644 --- a/v3/static.go +++ b/v3/static.go @@ -145,7 +145,7 @@ func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte { func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name } func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize } -func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 } +func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0o444 } func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime } func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false } func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil } @@ -180,6 +180,7 @@ func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { f.seekPos = f.grPos return n, err } + func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { switch whence { case io.SeekStart: @@ -193,6 +194,7 @@ func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { } return f.seekPos, nil } + func (f *vfsgen۰CompressedFile) Close() error { return f.gr.Close() } @@ -213,7 +215,7 @@ func (f *vfsgen۰FileInfo) NotWorthGzipCompressing() {} func (f *vfsgen۰FileInfo) Name() string { return f.name } func (f *vfsgen۰FileInfo) Size() int64 { return int64(len(f.content)) } -func (f *vfsgen۰FileInfo) Mode() os.FileMode { return 0444 } +func (f *vfsgen۰FileInfo) Mode() os.FileMode { return 0o444 } func (f *vfsgen۰FileInfo) ModTime() time.Time { return f.modTime } func (f *vfsgen۰FileInfo) IsDir() bool { return false } func (f *vfsgen۰FileInfo) Sys() interface{} { return nil } @@ -243,7 +245,7 @@ func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil } func (d *vfsgen۰DirInfo) Name() string { return d.name } func (d *vfsgen۰DirInfo) Size() int64 { return 0 } -func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } +func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0o755 | os.ModeDir } func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime } func (d *vfsgen۰DirInfo) IsDir() bool { return true } func (d *vfsgen۰DirInfo) Sys() interface{} { return nil } diff --git a/v3/static/embed.go b/v3/static/embed.go index 3522c04..ca7e336 100644 --- a/v3/static/embed.go +++ b/v3/static/embed.go @@ -9,5 +9,6 @@ import ( ) // FS holds embedded assets. +// //go:embed *.png *.gz var FS embed.FS diff --git a/v3cdn/handler.go b/v3cdn/handler.go index 45bf1ff..f75d566 100644 --- a/v3cdn/handler.go +++ b/v3cdn/handler.go @@ -10,6 +10,25 @@ import ( // Handler handle swagger UI request. type Handler = internal.Handler +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // New creates HTTP handler for Swagger UI. func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath) diff --git a/v3emb/handler.go b/v3emb/handler.go index d69d12d..16c776b 100644 --- a/v3emb/handler.go +++ b/v3emb/handler.go @@ -11,6 +11,25 @@ import ( // Handler handles swagger UI request. type Handler = internal.Handler +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // New creates HTTP handler for Swagger UI. func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath) diff --git a/v4/gen/gen.go b/v4/gen/gen.go index 54433e1..a43735f 100644 --- a/v4/gen/gen.go +++ b/v4/gen/gen.go @@ -1,3 +1,4 @@ +// Package main generates legacy static assets. package main import ( diff --git a/v4/handler.go b/v4/handler.go index 36d83a8..e8d80a8 100644 --- a/v4/handler.go +++ b/v4/handler.go @@ -11,6 +11,25 @@ import ( // Handler handles swagger UI request. type Handler = internal.Handler +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // New creates HTTP handler for Swagger UI. func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath) diff --git a/v4/static.go b/v4/static.go index 9ed6f39..6c659a8 100644 --- a/v4/static.go +++ b/v4/static.go @@ -145,7 +145,7 @@ func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte { func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name } func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize } -func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 } +func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0o444 } func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime } func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false } func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil } @@ -180,6 +180,7 @@ func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { f.seekPos = f.grPos return n, err } + func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { switch whence { case io.SeekStart: @@ -193,6 +194,7 @@ func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { } return f.seekPos, nil } + func (f *vfsgen۰CompressedFile) Close() error { return f.gr.Close() } @@ -213,7 +215,7 @@ func (f *vfsgen۰FileInfo) NotWorthGzipCompressing() {} func (f *vfsgen۰FileInfo) Name() string { return f.name } func (f *vfsgen۰FileInfo) Size() int64 { return int64(len(f.content)) } -func (f *vfsgen۰FileInfo) Mode() os.FileMode { return 0444 } +func (f *vfsgen۰FileInfo) Mode() os.FileMode { return 0o444 } func (f *vfsgen۰FileInfo) ModTime() time.Time { return f.modTime } func (f *vfsgen۰FileInfo) IsDir() bool { return false } func (f *vfsgen۰FileInfo) Sys() interface{} { return nil } @@ -243,7 +245,7 @@ func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil } func (d *vfsgen۰DirInfo) Name() string { return d.name } func (d *vfsgen۰DirInfo) Size() int64 { return 0 } -func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } +func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0o755 | os.ModeDir } func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime } func (d *vfsgen۰DirInfo) IsDir() bool { return true } func (d *vfsgen۰DirInfo) Sys() interface{} { return nil } diff --git a/v4/static/embed.go b/v4/static/embed.go index 6cf9614..08c5533 100644 --- a/v4/static/embed.go +++ b/v4/static/embed.go @@ -8,6 +8,7 @@ import ( "embed" ) -//go:embed *.png *.gz // FS holds embedded static assets. +// +//go:embed *.png *.gz var FS embed.FS diff --git a/v4cdn/handler.go b/v4cdn/handler.go index eacd002..1f1ffb8 100644 --- a/v4cdn/handler.go +++ b/v4cdn/handler.go @@ -11,6 +11,25 @@ import ( // Handler handle swagger UI request. type Handler = internal.Handler +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // New creates HTTP handler for Swagger UI. func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath) diff --git a/v4emb/handler.go b/v4emb/handler.go index 15db217..bbd2334 100644 --- a/v4emb/handler.go +++ b/v4emb/handler.go @@ -11,6 +11,25 @@ import ( // Handler handles swagger UI request. type Handler = internal.Handler +// NewWithConfig creates configurable handler constructor. +func NewWithConfig(config swgui.Config) func(title, swaggerJSONPath string, basePath string) http.Handler { + return func(title, swaggerJSONPath string, basePath string) http.Handler { + if config.Title == "" { + config.Title = title + } + + if config.SwaggerJSON == "" { + config.SwaggerJSON = swaggerJSONPath + } + + if config.BasePath == "" { + config.BasePath = basePath + } + + return NewHandlerWithConfig(config) + } +} + // New creates HTTP handler for Swagger UI. func New(title, swaggerJSONPath string, basePath string) http.Handler { return NewHandler(title, swaggerJSONPath, basePath)