diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2020-10-05 21:01:52 +0300 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2020-10-06 15:06:10 +0300 |
commit | c63db7f1f6774a2d661af1d8197c6fe377e3ad25 (patch) | |
tree | bbeccc7dd4f41acdcc1cfd584ea351e6284869d5 /resources | |
parent | 5e2a547cb594b31ecb0f089b08db2e15c6dc381a (diff) |
Allow cascade to be a slice with a _target discriminator
Fixes #7782
Diffstat (limited to 'resources')
-rw-r--r-- | resources/page/page_matcher.go | 91 | ||||
-rw-r--r-- | resources/page/page_matcher_test.go | 63 | ||||
-rw-r--r-- | resources/page/testhelpers_test.go | 9 |
3 files changed, 159 insertions, 4 deletions
diff --git a/resources/page/page_matcher.go b/resources/page/page_matcher.go new file mode 100644 index 000000000..881f76e33 --- /dev/null +++ b/resources/page/page_matcher.go @@ -0,0 +1,91 @@ +// 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 page + +import ( + "path/filepath" + "strings" + + "github.com/pkg/errors" + + "github.com/gohugoio/hugo/hugofs/glob" + "github.com/mitchellh/mapstructure" +) + +// A PageMatcher can be used to match a Page with Glob patterns. +// Note that the pattern matching is case insensitive. +type PageMatcher struct { + // A Glob pattern matching the content path below /content. + // Expects Unix-styled slashes. + // Note that this is the virtual path, so it starts at the mount root + // with a leading "/". + Path string + + // A Glob pattern matching the Page's Kind(s), e.g. "{home,section}" + Kind string + + // A Glob pattern matching the Page's language, e.g. "{en,sv}". + Lang string +} + +// Matches returns whether p matches this matcher. +func (m PageMatcher) Matches(p Page) bool { + + if m.Kind != "" { + g, err := glob.GetGlob(m.Kind) + if err == nil && !g.Match(p.Kind()) { + return false + } + } + + if m.Lang != "" { + g, err := glob.GetGlob(m.Lang) + if err == nil && !g.Match(p.Lang()) { + return false + } + } + + if m.Path != "" { + g, err := glob.GetGlob(m.Path) + // TODO(bep) Path() vs filepath vs leading slash. + p := strings.ToLower(filepath.ToSlash(p.Path())) + if !(strings.HasPrefix(p, "/")) { + p = "/" + p + } + if err == nil && !g.Match(p) { + return false + } + } + + return true +} + +// DecodePageMatcher decodes m into v. +func DecodePageMatcher(m interface{}, v *PageMatcher) error { + if err := mapstructure.WeakDecode(m, v); err != nil { + return err + } + + v.Kind = strings.ToLower(v.Kind) + if v.Kind != "" { + if _, found := kindMap[v.Kind]; !found { + return errors.Errorf("%q is not a valid Page Kind", v.Kind) + } + } + + v.Path = filepath.ToSlash(strings.ToLower(v.Path)) + + return nil + +} diff --git a/resources/page/page_matcher_test.go b/resources/page/page_matcher_test.go new file mode 100644 index 000000000..24b304772 --- /dev/null +++ b/resources/page/page_matcher_test.go @@ -0,0 +1,63 @@ +// 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 page + +import ( + "path/filepath" + "testing" + + qt "github.com/frankban/quicktest" +) + +func TestPageMatcher(t *testing.T) { + c := qt.New(t) + + p1, p2, p3 := &testPage{path: "/p1", kind: "section", lang: "en"}, &testPage{path: "p2", kind: "page", lang: "no"}, &testPage{path: "p3", kind: "page", lang: "en"} + + c.Run("Matches", func(c *qt.C) { + m := PageMatcher{Kind: "section"} + + c.Assert(m.Matches(p1), qt.Equals, true) + c.Assert(m.Matches(p2), qt.Equals, false) + + m = PageMatcher{Kind: "page"} + c.Assert(m.Matches(p1), qt.Equals, false) + c.Assert(m.Matches(p2), qt.Equals, true) + c.Assert(m.Matches(p3), qt.Equals, true) + + m = PageMatcher{Kind: "page", Path: "/p2"} + c.Assert(m.Matches(p1), qt.Equals, false) + c.Assert(m.Matches(p2), qt.Equals, true) + c.Assert(m.Matches(p3), qt.Equals, false) + + m = PageMatcher{Path: "/p*"} + c.Assert(m.Matches(p1), qt.Equals, true) + c.Assert(m.Matches(p2), qt.Equals, true) + c.Assert(m.Matches(p3), qt.Equals, true) + + m = PageMatcher{Lang: "en"} + c.Assert(m.Matches(p1), qt.Equals, true) + c.Assert(m.Matches(p2), qt.Equals, false) + c.Assert(m.Matches(p3), qt.Equals, true) + + }) + + c.Run("Decode", func(c *qt.C) { + var v PageMatcher + c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "foo"}, &v), qt.Not((qt.IsNil))) + c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "home", "path": filepath.FromSlash("/a/b/**")}, &v), qt.IsNil) + c.Assert(v, qt.Equals, PageMatcher{Kind: "home", Path: "/a/b/**"}) + }) + +} diff --git a/resources/page/testhelpers_test.go b/resources/page/testhelpers_test.go index 17a795a20..54a908d3b 100644 --- a/resources/page/testhelpers_test.go +++ b/resources/page/testhelpers_test.go @@ -85,11 +85,12 @@ func newTestPathSpecFor(cfg config.Provider) *helpers.PathSpec { } type testPage struct { + kind string description string title string linkTitle string - - section string + lang string + section string content string @@ -297,11 +298,11 @@ func (p *testPage) Keywords() []string { } func (p *testPage) Kind() string { - panic("not implemented") + return p.kind } func (p *testPage) Lang() string { - panic("not implemented") + return p.lang } func (p *testPage) Language() *langs.Language { |