From 3e42c2a2b98ab17bf6a2c5b0d4c9b63b0a2ba033 Mon Sep 17 00:00:00 2001 From: Richard Kettelerij Date: Tue, 17 Sep 2024 20:08:38 +0200 Subject: [PATCH 1/3] fix(order): fix collection order since the unique() func lost order when displaying collections --- config/collections.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/config/collections.go b/config/collections.go index 375e4153..2beb64de 100644 --- a/config/collections.go +++ b/config/collections.go @@ -6,6 +6,7 @@ import ( "sort" "dario.cat/mergo" + orderedmap "github.com/wk8/go-ordered-map/v2" "gopkg.in/yaml.v3" ) @@ -182,37 +183,40 @@ func (c *Config) AllCollections() GeoSpatialCollections { return result } -// Unique lists all unique GeoSpatialCollections (no duplicate IDs) +// Unique lists all unique GeoSpatialCollections (no duplicate IDs). +// Don't use in hot path (creates a map on every invocation). func (g GeoSpatialCollections) Unique() []GeoSpatialCollection { collectionsByID := g.toMap() - result := make([]GeoSpatialCollection, 0, len(collectionsByID)) - for _, v := range collectionsByID { - result = append(result, v) + result := make([]GeoSpatialCollection, 0, collectionsByID.Len()) + for pair := collectionsByID.Oldest(); pair != nil; pair = pair.Next() { + result = append(result, pair.Value) } return result } // ContainsID check if given collection - by ID - exists. +// Don't use in hot path (creates a map on every invocation). func (g GeoSpatialCollections) ContainsID(id string) bool { - _, ok := g.toMap()[id] + collectionsByID := g.toMap() + _, ok := collectionsByID.Get(id) return ok } -func (g GeoSpatialCollections) toMap() map[string]GeoSpatialCollection { - collectionsByID := make(map[string]GeoSpatialCollection) +func (g GeoSpatialCollections) toMap() orderedmap.OrderedMap[string, GeoSpatialCollection] { + collectionsByID := orderedmap.New[string, GeoSpatialCollection]() for _, current := range g { - existing, ok := collectionsByID[current.ID] + existing, ok := collectionsByID.Get(current.ID) if ok { err := mergo.Merge(&existing, current) if err != nil { log.Fatalf("failed to merge 2 collections with the same name '%s': %v", current.ID, err) } - collectionsByID[current.ID] = existing + collectionsByID.Set(current.ID, existing) } else { - collectionsByID[current.ID] = current + collectionsByID.Set(current.ID, current) } } - return collectionsByID + return *collectionsByID } func sortByAlphabet(collection []GeoSpatialCollection) { From 1616017dd6f2aa09cf281e758dcb71cec44433e3 Mon Sep 17 00:00:00 2001 From: Richard Kettelerij Date: Tue, 17 Sep 2024 20:10:15 +0200 Subject: [PATCH 2/3] fix(linking): only link url's that aren't surrounded by additional text. Since GML (containing namespace url's) was mistakenly rendered as hyperlinks. --- internal/engine/templatefuncs.go | 4 +- internal/engine/templatefuncs_test.go | 64 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/internal/engine/templatefuncs.go b/internal/engine/templatefuncs.go index d377f4b0..05217464 100644 --- a/internal/engine/templatefuncs.go +++ b/internal/engine/templatefuncs.go @@ -20,7 +20,7 @@ import ( var ( globalTemplateFuncs texttemplate.FuncMap - linkRegex = regexp.MustCompile(`https?://\S+`) + linkRegex = regexp.MustCompile(`^https?://\S+$`) ) // Initialize functions to be used in html/json/etc templates @@ -115,7 +115,7 @@ func isDate(v any) bool { return false } -// isLink true when given input is an HTTP(s) URL, false otherwise +// isLink true when given input is an HTTP(s) URL (without any additional text), false otherwise func isLink(v any) bool { if text, ok := v.(string); ok { return linkRegex.MatchString(text) diff --git a/internal/engine/templatefuncs_test.go b/internal/engine/templatefuncs_test.go index fd56c34e..659aeace 100644 --- a/internal/engine/templatefuncs_test.go +++ b/internal/engine/templatefuncs_test.go @@ -99,6 +99,70 @@ func TestIsDate(t *testing.T) { } } +func TestIsLink(t *testing.T) { + tests := []struct { + name string + input any + expected bool + }{ + { + name: "Valid HTTP URL", + input: "http://example.com", + expected: true, + }, + { + name: "Valid HTTPS URL", + input: "https://example.com", + expected: true, + }, + { + name: "Invalid URL without scheme", + input: "example.com", + expected: false, + }, + { + name: "Invalid string with no URL", + input: "not a url", + expected: false, + }, + { + name: "Non-string input (integer)", + input: 12345, + expected: false, + }, + { + name: "Non-string input (struct)", + input: struct{}{}, + expected: false, + }, + { + name: "Empty string", + input: "", + expected: false, + }, + { + name: "URL with trailing characters", + input: "http://example.com foo bar", + expected: false, + }, + { + name: "URL with leading characters", + input: "foo bar http://example.com", + expected: false, + }, + { + name: "URL with special characters", + input: "http://example.com/path?query=param#fragment", + expected: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, isLink(tt.input)) + }) + } +} + func ptrTo(s string) *string { return &s } From 8c63f4daff5a3dc19909e4cf525feac264d8d496 Mon Sep 17 00:00:00 2001 From: Richard Kettelerij Date: Tue, 17 Sep 2024 20:17:05 +0200 Subject: [PATCH 3/3] fix(build): fix build --- hack/crd/go.mod | 4 ++++ hack/crd/go.sum | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/hack/crd/go.mod b/hack/crd/go.mod index 033ebd74..39c762d6 100644 --- a/hack/crd/go.mod +++ b/hack/crd/go.mod @@ -9,6 +9,8 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/creasty/defaults v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elnormous/contenttype v1.0.4 // indirect @@ -21,8 +23,10 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sys v0.21.0 // indirect diff --git a/hack/crd/go.sum b/hack/crd/go.sum index 37eef658..0e7e037f 100644 --- a/hack/crd/go.sum +++ b/hack/crd/go.sum @@ -1,5 +1,9 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA= github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,12 +33,15 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -48,6 +55,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=