Skip to content

Commit 931bea4

Browse files
committed
chore: fix zog schema regex
1 parent 59838cc commit 931bea4

5 files changed

Lines changed: 66 additions & 5 deletions

File tree

docs/static/zss/0.0.1/schema.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"properties": {
3232
"content": {},
3333
"uri": {
34-
"pattern": "^(?P\u003cid\u003ehttps?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?P\u003cversion\u003e(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
34+
"pattern": "^(?:https?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?:(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
3535
"type": "string"
3636
}
3737
},
@@ -225,7 +225,7 @@
225225
"type": "object"
226226
},
227227
"$schema": {
228-
"pattern": "^(?P\u003cid\u003ehttps?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?P\u003cversion\u003e(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
228+
"pattern": "^(?:https?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?:(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
229229
"type": "string"
230230
},
231231
"root": {
@@ -252,7 +252,7 @@
252252
"properties": {
253253
"content": {},
254254
"uri": {
255-
"pattern": "^(?P\u003cid\u003ehttps?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?P\u003cversion\u003e(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
255+
"pattern": "^(?:https?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?:(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
256256
"type": "string"
257257
}
258258
},
@@ -470,7 +470,7 @@
470470
"properties": {
471471
"content": {},
472472
"uri": {
473-
"pattern": "^(?P\u003cid\u003ehttps?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?P\u003cversion\u003e(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
473+
"pattern": "^(?:https?://[A-Za-z0-9.-]+(?::[0-9]+)?(?:/[A-Za-z0-9._~!$\u0026'()*+,;=:@%-]+)+)/(?:(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)(?:-beta(?:\\.(?:0|[1-9][0-9]*))?)?)/schema\\.json$",
474474
"type": "string"
475475
}
476476
},

pkgs/zss/jsonschema/draft2020_12/jsonschema.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
zsscore "github.com/Oudwins/zog/pkgs/zss/core"
1010
"github.com/Oudwins/zog/pkgs/zss/jsonschema/shared"
11+
"github.com/Oudwins/zog/pkgs/zss/regexconv"
1112
"github.com/Oudwins/zog/zconst"
1213
)
1314

@@ -254,7 +255,11 @@ func ConvertTest(out Schema, kind zconst.ZogType, test *zsscore.ZSSTest) error {
254255
case zconst.IssueCodeIP:
255256
out["format"] = "ip"
256257
case zconst.IssueCodeMatch:
257-
out["pattern"] = test.Params[zconst.IssueCodeMatch]
258+
pattern, ok := test.Params[zconst.IssueCodeMatch].(string)
259+
if !ok {
260+
return fmt.Errorf("match test param must be a string")
261+
}
262+
out["pattern"] = regexconv.GoRE2ToECMA262(pattern)
258263
case zconst.IssueCodeTrue:
259264
out["const"] = true
260265
case zconst.IssueCodeFalse:

pkgs/zss/jsonschema/jsonschema_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package zjsonschema_test
33
import (
44
"encoding/json"
55
"errors"
6+
"regexp"
67
"testing"
78

89
zsscore "github.com/Oudwins/zog/pkgs/zss/core"
@@ -197,6 +198,30 @@ func TestFromZSSConvertsCustomTestsWithOption(t *testing.T) {
197198
assert.Equal(t, "^z", schema["pattern"])
198199
}
199200

201+
func TestFromZSSConvertsNamedGroupsInMatchPatterns(t *testing.T) {
202+
doc := zsscore.ZSSDocument{Root: &zsscore.ZSSSchema{Kind: zconst.TypeString, Processors: []zsscore.ZSSProcessor{
203+
testProcessor(zconst.IssueCodeMatch, map[string]any{zconst.IssueCodeMatch: regexp.MustCompile(`^(?P<id>[a-z]+)/(?P<version>[0-9]+)$`).String()}),
204+
}}}
205+
206+
schema, err := zjsonschema.FromZSS(doc, zjsonschema.Options{})
207+
require.NoError(t, err)
208+
requireValidJSONSchema(t, schema)
209+
210+
assert.Equal(t, `^(?:[a-z]+)/(?:[0-9]+)$`, schema["pattern"])
211+
}
212+
213+
func TestFromZSSReturnsErrorForNonStringMatchPattern(t *testing.T) {
214+
doc := zsscore.ZSSDocument{Root: &zsscore.ZSSSchema{Kind: zconst.TypeString, Processors: []zsscore.ZSSProcessor{
215+
testProcessor(zconst.IssueCodeMatch, map[string]any{zconst.IssueCodeMatch: 1}),
216+
}}}
217+
218+
_, err := zjsonschema.FromZSS(doc, zjsonschema.Options{})
219+
220+
require.Error(t, err)
221+
assert.ErrorContains(t, err, `convert test "match"`)
222+
assert.ErrorContains(t, err, "match test param must be a string")
223+
}
224+
200225
func TestFromZSSReturnsTestConverterErrors(t *testing.T) {
201226
wantErr := errors.New("custom test failed")
202227
doc := zsscore.ZSSDocument{Root: &zsscore.ZSSSchema{Kind: zconst.TypeString, Processors: []zsscore.ZSSProcessor{

pkgs/zss/regexconv/regexconv.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package regexconv
2+
3+
import "regexp"
4+
5+
var pythonNamedGroupPattern = regexp.MustCompile(`\(\?P<[^>]+>`)
6+
7+
// GoRE2ToECMA262 converts Go/RE2 regex syntax to ECMA-262 syntax.
8+
// For now, it only removes Go-supported Python-style named capture groups.
9+
func GoRE2ToECMA262(pattern string) string {
10+
return pythonNamedGroupPattern.ReplaceAllString(pattern, "(?:")
11+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package regexconv
2+
3+
import (
4+
"regexp"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestGoRE2ToECMA262ConvertsPythonStyleNamedGroups(t *testing.T) {
11+
pattern := regexp.MustCompile(`^(?P<id>[a-z]+)/(?P<version>[0-9]+)$`).String()
12+
13+
assert.Equal(t, `^(?:[a-z]+)/(?:[0-9]+)$`, GoRE2ToECMA262(pattern))
14+
}
15+
16+
func TestGoRE2ToECMA262LeavesOtherSyntaxUnchanged(t *testing.T) {
17+
pattern := `^(?<id>[a-z]+)/(?:[0-9]+)$`
18+
19+
assert.Equal(t, pattern, GoRE2ToECMA262(pattern))
20+
}

0 commit comments

Comments
 (0)