From 2977711b192b7bd067c308a86bb75a2ad15aaa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 30 Jun 2020 16:11:05 +0200 Subject: [PATCH] Add openapi3.Unmarshal Fixes #7442 Fixes #7443 --- go.mod | 3 +- go.sum | 6 ++++ tpl/openapi/openapi3/init.go | 42 ++++++++++++++++++++++++++ tpl/openapi/openapi3/openapi3.go | 52 ++++++++++++++++++++++++++++++++ tpl/tplimpl/template_funcs.go | 1 + tpl/transform/unmarshal.go | 16 +++++++--- 6 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tpl/openapi/openapi3/init.go create mode 100644 tpl/openapi/openapi3/openapi3.go diff --git a/go.mod b/go.mod index ad6ecda86a0..6cf09720e7c 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/fortytw2/leaktest v1.3.0 github.com/frankban/quicktest v1.7.2 github.com/fsnotify/fsnotify v1.4.7 + github.com/getkin/kin-openapi v0.14.0 github.com/gobwas/glob v0.2.3 github.com/gohugoio/testmodBuilder/mods v0.0.0-20190520184928-c56af20f2e95 github.com/google/go-cmp v0.3.2-0.20191028172631-481baca67f93 @@ -65,7 +66,7 @@ require ( google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/ini.v1 v1.51.1 // indirect - gopkg.in/yaml.v2 v2.2.7 + gopkg.in/yaml.v2 v2.3.0 ) replace github.com/markbates/inflect => github.com/markbates/inflect v0.0.0-20171215194931-a12c3aec81a6 diff --git a/go.sum b/go.sum index 98f010ece2b..7549b18227e 100644 --- a/go.sum +++ b/go.sum @@ -127,6 +127,9 @@ github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3B github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/getkin/kin-openapi v0.14.0 h1:hqwQL7kze/adt0wB+0UJR2nJm+gfUHqM0Gu4D8nByVc= +github.com/getkin/kin-openapi v0.14.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -352,6 +355,7 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tdewolff/minify/v2 v2.6.1 h1:UJLhbs2Q/iDrqA79EEyKE48uYHeAMPVdiUzdtKsatJ8= @@ -550,6 +554,8 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/tpl/openapi/openapi3/init.go b/tpl/openapi/openapi3/init.go new file mode 100644 index 00000000000..1e1a4ae05f1 --- /dev/null +++ b/tpl/openapi/openapi3/init.go @@ -0,0 +1,42 @@ +// Copyright 2020 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openapi3 + +import ( + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/tpl/internal" +) + +const name = "openapi3" + +func init() { + f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { + ctx := New(d) + + ns := &internal.TemplateFuncsNamespace{ + Name: name, + Context: func(args ...interface{}) interface{} { return ctx }, + } + + ns.AddMethodMapping(ctx.Unmarshal, + nil, + [][2]string{}, + ) + + return ns + + } + + internal.AddTemplateFuncsNamespace(f) +} diff --git a/tpl/openapi/openapi3/openapi3.go b/tpl/openapi/openapi3/openapi3.go new file mode 100644 index 00000000000..30987b02508 --- /dev/null +++ b/tpl/openapi/openapi3/openapi3.go @@ -0,0 +1,52 @@ +// Copyright 2020 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package openapi3 + +import ( + kopenapi3 "github.com/getkin/kin-openapi/openapi3" + "github.com/gohugoio/hugo/cache/namedmemcache" + "github.com/gohugoio/hugo/deps" + "github.com/gohugoio/hugo/resources/resource" +) + +// New returns a new instance of the openapi3-namespaced template functions. +func New(deps *deps.Deps) *Namespace { + // TODO1 consolidate when merging that "other branch" + cache := namedmemcache.New() + deps.BuildStartListeners.Add( + func() { + cache.Clear() + }) + + return &Namespace{ + cache: cache, + deps: deps, + } +} + +// Namespace provides template functions for the "openapi3". +type Namespace struct { + cache *namedmemcache.Cache + deps *deps.Deps +} + +func (ns *Namespace) Unmarshal(r resource.ContentResource) (*kopenapi3.Swagger, error) { + c, err := r.Content() + if err != nil { + return nil, err + } + + return kopenapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(c.(string))) + +} diff --git a/tpl/tplimpl/template_funcs.go b/tpl/tplimpl/template_funcs.go index ccf33d8ba25..9141de3f17f 100644 --- a/tpl/tplimpl/template_funcs.go +++ b/tpl/tplimpl/template_funcs.go @@ -44,6 +44,7 @@ import ( _ "github.com/gohugoio/hugo/tpl/inflect" _ "github.com/gohugoio/hugo/tpl/lang" _ "github.com/gohugoio/hugo/tpl/math" + _ "github.com/gohugoio/hugo/tpl/openapi/openapi3" _ "github.com/gohugoio/hugo/tpl/os" _ "github.com/gohugoio/hugo/tpl/partials" _ "github.com/gohugoio/hugo/tpl/path" diff --git a/tpl/transform/unmarshal.go b/tpl/transform/unmarshal.go index da06b6aa124..7540f67c0ee 100644 --- a/tpl/transform/unmarshal.go +++ b/tpl/transform/unmarshal.go @@ -14,6 +14,7 @@ package transform import ( + "encoding/json" "io/ioutil" "strings" @@ -27,7 +28,7 @@ import ( "github.com/spf13/cast" ) -// Unmarshal unmarshals the data given, which can be either a string +// Unmarshal unmarshals the data given, which can be either a string, json.RawMessage // or a Resource. Supported formats are JSON, TOML, YAML, and CSV. // You can optionally provide an options map as the first argument. func (ns *Namespace) Unmarshal(args ...interface{}) (interface{}, error) { @@ -87,9 +88,16 @@ func (ns *Namespace) Unmarshal(args ...interface{}) (interface{}, error) { }) } - dataStr, err := cast.ToStringE(data) - if err != nil { - return nil, errors.Errorf("type %T not supported", data) + var dataStr string + + if js, ok := data.(json.RawMessage); ok { + dataStr = string(js) + } else { + var err error + dataStr, err = cast.ToStringE(data) + if err != nil { + return nil, errors.Errorf("type %T not supported", data) + } } key := helpers.MD5String(dataStr)