Skip to content

Commit

Permalink
Add ScriptSrcs to add extra scripts URLs to load
Browse files Browse the repository at this point in the history
Summary: This allows importing plugins from local and external hosts.

```
	r.Get("/swagger/*", httpSwagger.Handler(
		httpSwagger.ScriptSrc("/static/swagger-helper.js"),
		httpSwagger.ScriptSrc("https://unpkg.com/[email protected]/build/index.js"),
		httpSwagger.Plugins([]string{"DisableTryItOutWithoutServersPlugin"},
		httpSwagger.URL("http://localhost:1323/swagger/doc.json"), //The url pointing to API definition
	))
```

Closes swaggo#83

Test Plan: Updated existing tests. Added example in example/go-chi/
  • Loading branch information
Zhomart committed Jan 13, 2023
1 parent 1429310 commit d231c34
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 58 deletions.
71 changes: 13 additions & 58 deletions example/go-chi/docs/docs.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// Package docs GENERATED BY SWAG; DO NOT EDIT
// This file was generated by swaggo/swag
package docs

import (
"bytes"
"encoding/json"
"strings"
"text/template"
import "github.com/swaggo/swag"

"github.com/swaggo/swag"
)

var doc = `{
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
Expand All @@ -34,56 +27,18 @@ var doc = `{
"paths": {}
}`

type swaggerInfo struct {
Version string
Host string
BasePath string
Schemes []string
Title string
Description string
}

// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "1.0",
Host: "petstore.swagger.io",
BasePath: "/v2",
Schemes: []string{},
Title: "Swagger Example API",
Description: "This is a sample server Petstore server.",
}

type s struct{}

func (s *s) ReadDoc() string {
sInfo := SwaggerInfo
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)

t, err := template.New("swagger_info").Funcs(template.FuncMap{
"marshal": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
"escape": func(v interface{}) string {
// escape tabs
str := strings.Replace(v.(string), "\t", "\\t", -1)
// replace " with \", and if that results in \\", replace that with \\\"
str = strings.Replace(str, "\"", "\\\"", -1)
return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1)
},
}).Parse(doc)
if err != nil {
return doc
}

var tpl bytes.Buffer
if err := t.Execute(&tpl, sInfo); err != nil {
return doc
}

return tpl.String()
var SwaggerInfo = &swag.Spec{
Version: "1.0",
Host: "petstore.swagger.io",
BasePath: "/v2",
Schemes: []string{},
Title: "Swagger Example API",
Description: "This is a sample server Petstore server.",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
}

func init() {
swag.Register(swag.Name, &s{})
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}
4 changes: 4 additions & 0 deletions example/go-chi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func main() {
r.Get("/swagger/*", httpSwagger.Handler(
httpSwagger.BeforeScript("console.log('before 1')"),
httpSwagger.BeforeScript("console.log('before 2')"),
httpSwagger.ScriptSrc("https://unpkg.com/[email protected]/dist/htm.js"),
httpSwagger.ScriptSrc("https://unpkg.com/[email protected]/umd/react.production.min.js"),
httpSwagger.ScriptSrc("/static/myplugin.js"),
httpSwagger.Plugins([]string{"MyPlugin"}),
httpSwagger.URL("http://localhost:1323/swagger/doc.json"), //The url pointing to API definition
))

Expand Down
80 changes: 80 additions & 0 deletions example/go-chi/static/myplugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Swagger UI Version: 4.15.5

'use strict';

function _typeof(obj) {
if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
_typeof = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof = function _typeof(obj) {
return obj &&
typeof Symbol === 'function' &&
obj.constructor === Symbol &&
obj !== Symbol.prototype
? 'symbol'
: typeof obj;
};
}
return _typeof(obj);
}

// From: https://raw.githubusercontent.com/chilts/umd-template/master/template.js
(function (f) {
// module name and requires
var name = 'MyPlugin';
var requires = []; // CommonJS

if (
(typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' &&
typeof module !== 'undefined'
) {
module.exports = f.apply(
null,
requires.map(function (r) {
return require(r);
})
); // RequireJS
} else if (typeof define === 'function' && define.amd) {
define(requires, f); // <script>
} else {
var g;

if (typeof window !== 'undefined') {
g = window;
} else if (typeof global !== 'undefined') {
g = global;
} else if (typeof self !== 'undefined') {
g = self;
} else {
// works providing we're not in "use strict";
// needed for Java 8 Nashorn
// seee https://github.com/facebook/react/issues/3037
g = this;
}

g[name] = f.apply(
null,
requires.map(function (r) {
return g[r];
})
);
}
})(function () {
return function (system) {
return {
wrapComponents: {
info: (Original, system) => (props) => {
const html = htm.bind(React.createElement);
// Uses https://github.com/developit/htm to render JSX.
return html`
<div>
<h3>Hello world! I am above the Info component.</h3>
<Original {...props} />
</div>`;
}
},
};
};
});
11 changes: 11 additions & 0 deletions swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Config struct {
BeforeScripts []template.JS
AfterScripts []template.JS
Plugins []template.JS
ScriptSrcs []string // URLs to the extra scripts to load
UIConfig map[template.JS]template.JS
DeepLinking bool
PersistAuthorization bool
Expand Down Expand Up @@ -84,6 +85,13 @@ func Plugins(plugins []string) func(*Config) {
}
}

// Adds `<script src="src"></script>`
func ScriptSrc(src string) func(*Config) {
return func(c *Config) {
c.ScriptSrcs = append(c.ScriptSrcs, src)
}
}

// UIConfig specifies additional SwaggerUIBundle config object properties.
func UIConfig(props map[string]string) func(*Config) {
return func(c *Config) {
Expand Down Expand Up @@ -259,6 +267,9 @@ const indexTempl = `<!-- HTML for static distribution bundle build -->
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
{{- range $script := .ScriptSrcs }}
<script src="{{$script}}"> </script>
{{- end}}
<script>
window.onload = function() {
{{- range $script := .BeforeScripts }}
Expand Down
11 changes: 11 additions & 0 deletions swagger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ func TestConfigURL(t *testing.T) {
// Some plugin
});`),
},
{
desc: "configure ScriptSrcs",
exp: &Config{
ScriptSrcs: []string{`/scripts/helper.js`},
},
cfgfn: ScriptSrc(`/scripts/helper.js`),
},
}

for _, fix := range fixtures {
Expand Down Expand Up @@ -335,6 +342,8 @@ func TestUIConfigOptions(t *testing.T) {
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script src="./a.js"> </script>
<script src="./b.js"> </script>
<script>
`
ftr := `
Expand All @@ -353,6 +362,7 @@ func TestUIConfigOptions(t *testing.T) {
DocExpansion: "list",
DomID: "swagger-ui",
PersistAuthorization: false,
ScriptSrcs: []string{"./a.js", "./b.js"},
},
exp: `window.onload = function() {
Expand Down Expand Up @@ -396,6 +406,7 @@ func TestUIConfigOptions(t *testing.T) {
"SomePlugin",
"AnotherPlugin",
},
ScriptSrcs: []string{"./a.js", "./b.js"},
UIConfig: map[template.JS]template.JS{
"showExtensions": "true",
"onComplete": `() => { window.ui.setBasePath('v3'); }`,
Expand Down

0 comments on commit d231c34

Please sign in to comment.