Skip to content

Commit c569ff4

Browse files
committed
feat!: support multiple versions and redesign the API
Fix italia#75.
1 parent 3ececf5 commit c569ff4

21 files changed

+1157
-484
lines changed

fields.go

+46-41
Original file line numberDiff line numberDiff line change
@@ -3,111 +3,112 @@ package publiccode
33
import (
44
"fmt"
55
"net/url"
6-
"slices"
76

87
spdxValidator "github.com/kyoh86/go-spdx/spdx"
98
"github.com/alranel/go-vcsurl/v2"
109

11-
urlutil "github.com/italia/publiccode-parser-go/v3/internal"
10+
urlutil "github.com/italia/publiccode-parser-go/v4/internal"
1211
)
1312

13+
type validateFn func (publiccode PublicCode, parser Parser, network bool) error
14+
1415
// validateFields validates publiccode with additional rules not validatable
1516
// with a simple YAML schema.
1617
// It returns any error encountered as ValidationResults.
17-
func (p *Parser) validateFields() error {
18+
func validateFieldsV0(publiccode PublicCode, parser Parser, network bool) error {
19+
publiccodev0 := publiccode.(PublicCodeV0)
20+
1821
var vr ValidationResults
1922
var err error
2023

21-
if (p.PublicCode.URL != nil) {
22-
if reachable, err := p.isReachable(*(*url.URL)(p.PublicCode.URL)); !reachable {
23-
vr = append(vr, newValidationError("url", "'%s' not reachable: %s", p.PublicCode.URL, err.Error()))
24+
if (publiccodev0.URL != nil && network) {
25+
if reachable, err := parser.isReachable(*(*url.URL)(publiccodev0.URL), network); !reachable {
26+
vr = append(vr, newValidationError("url", "'%s' not reachable: %s", publiccodev0.URL, err.Error()))
2427
}
25-
if !vcsurl.IsRepo((*url.URL)(p.PublicCode.URL)) {
28+
if !vcsurl.IsRepo((*url.URL)(publiccodev0.URL)) {
2629
vr = append(vr, newValidationError("url", "is not a valid code repository"))
2730
}
2831
}
2932

30-
if p.PublicCode.LandingURL != nil {
31-
if reachable, err := p.isReachable(*(*url.URL)(p.PublicCode.LandingURL)); !reachable {
33+
if publiccodev0.LandingURL != nil {
34+
if reachable, err := parser.isReachable(*(*url.URL)(publiccodev0.LandingURL), network); !reachable {
3235
vr = append(vr, newValidationError(
3336
"landingURL",
34-
"'%s' not reachable: %s", p.PublicCode.LandingURL, err.Error(),
37+
"'%s' not reachable: %s", publiccodev0.LandingURL, err.Error(),
3538
))
3639
}
3740
}
3841

39-
if p.PublicCode.Roadmap != nil {
40-
if reachable, err := p.isReachable(*(*url.URL)(p.PublicCode.Roadmap)); !reachable {
42+
if publiccodev0.Roadmap != nil {
43+
if reachable, err := parser.isReachable(*(*url.URL)(publiccodev0.Roadmap), network); !reachable {
4144
vr = append(vr, newValidationError(
4245
"roadmap",
43-
"'%s' not reachable: %s", p.PublicCode.Roadmap, err.Error(),
46+
"'%s' not reachable: %s", publiccodev0.Roadmap, err.Error(),
4447
))
4548
}
4649
}
4750

48-
if (p.PublicCode.Logo != "") {
49-
if validLogo, err := p.validLogo(p.toURL(p.PublicCode.Logo)); !validLogo {
51+
if (publiccodev0.Logo != "") {
52+
if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.Logo, parser.baseURL), parser, network); !validLogo {
5053
vr = append(vr, newValidationError("logo", err.Error()))
5154
}
5255
}
53-
if (p.PublicCode.MonochromeLogo != "") {
56+
if (publiccodev0.MonochromeLogo != "") {
5457
vr = append(vr, ValidationWarning{"monochromeLogo", "This key is DEPRECATED and will be removed in the future", 0, 0})
5558

56-
if validLogo, err := p.validLogo(p.toURL(p.PublicCode.MonochromeLogo)); !validLogo {
59+
if validLogo, err := parser.validLogo(toCodeHostingURL(publiccodev0.MonochromeLogo, parser.baseURL), parser, network); !validLogo {
5760
vr = append(vr, newValidationError("monochromeLogo", err.Error()))
5861
}
5962
}
6063

61-
if p.PublicCode.Legal.AuthorsFile != nil && !p.fileExists(p.toURL(*p.PublicCode.Legal.AuthorsFile)) {
62-
u := p.toURL(*p.PublicCode.Legal.AuthorsFile)
64+
if publiccodev0.Legal.AuthorsFile != nil && !parser.fileExists(toCodeHostingURL(*publiccodev0.Legal.AuthorsFile, parser.baseURL), network) {
65+
u := toCodeHostingURL(*publiccodev0.Legal.AuthorsFile, parser.baseURL)
6366

6467
vr = append(vr, newValidationError("legal.authorsFile", "'%s' does not exist", urlutil.DisplayURL(&u)))
6568
}
6669

67-
if p.PublicCode.Legal.License != "" {
68-
_, err = spdxValidator.Parse(p.PublicCode.Legal.License)
70+
if publiccodev0.Legal.License != "" {
71+
_, err = spdxValidator.Parse(publiccodev0.Legal.License)
6972
if err != nil {
7073
vr = append(vr, newValidationError(
7174
"legal.license",
72-
"invalid license '%s'", p.PublicCode.Legal.License,
75+
"invalid license '%s'", publiccodev0.Legal.License,
7376
))
7477
}
7578
}
7679

77-
if p.PublicCode.It.CountryExtensionVersion != "" &&
78-
!slices.Contains(ExtensionITSupportedVersions, p.PublicCode.It.CountryExtensionVersion) {
79-
80+
if publiccodev0.It.CountryExtensionVersion != "" && publiccodev0.It.CountryExtensionVersion != "0.2" {
8081
vr = append(vr, newValidationError(
8182
"it.countryExtensionVersion",
82-
"version %s not supported for 'it' extension", p.PublicCode.It.CountryExtensionVersion,
83+
"version %s not supported for country-specific section 'it'", publiccodev0.It.CountryExtensionVersion,
8384
))
8485
}
8586

86-
if len(p.PublicCode.InputTypes) > 0 {
87+
if len(publiccodev0.InputTypes) > 0 {
8788
vr = append(vr, ValidationWarning{"inputTypes", "This key is DEPRECATED and will be removed in the future", 0, 0})
8889
}
89-
for i, mimeType := range p.PublicCode.InputTypes {
90-
if !p.isMIME(mimeType) {
90+
for i, mimeType := range publiccodev0.InputTypes {
91+
if !isMIME(mimeType) {
9192
vr = append(vr, newValidationError(
9293
fmt.Sprintf("inputTypes[%d]", i), "'%s' is not a MIME type", mimeType,
9394
))
9495
}
9596
}
9697

97-
if len(p.PublicCode.OutputTypes) > 0 {
98+
if len(publiccodev0.OutputTypes) > 0 {
9899
vr = append(vr, ValidationWarning{"outputTypes", "This key is DEPRECATED and will be removed in the future", 0, 0})
99100
}
100-
for i, mimeType := range p.PublicCode.OutputTypes {
101-
if !p.isMIME(mimeType) {
101+
for i, mimeType := range publiccodev0.OutputTypes {
102+
if !isMIME(mimeType) {
102103
vr = append(vr, newValidationError(
103104
fmt.Sprintf("outputTypes[%d]", i), "'%s' is not a MIME type", mimeType,
104105
))
105106
}
106107
}
107108

108-
for lang, desc := range p.PublicCode.Description {
109-
if p.PublicCode.Description == nil {
110-
p.PublicCode.Description = make(map[string]Desc)
109+
for lang, desc := range publiccodev0.Description {
110+
if publiccodev0.Description == nil {
111+
publiccodev0.Description = make(map[string]DescV0)
111112
}
112113

113114
if len(desc.GenericName) > 0 {
@@ -117,16 +118,16 @@ func (p *Parser) validateFields() error {
117118
})
118119
}
119120

120-
if (desc.Documentation != nil) {
121-
if reachable, err := p.isReachable(*(*url.URL)(desc.Documentation)); !reachable {
121+
if network && desc.Documentation != nil {
122+
if reachable, err := parser.isReachable(*(*url.URL)(desc.Documentation), network); !reachable {
122123
vr = append(vr, newValidationError(
123124
fmt.Sprintf("description.%s.documentation", lang),
124125
"'%s' not reachable: %s", desc.Documentation, err.Error(),
125126
))
126127
}
127128
}
128-
if desc.APIDocumentation != nil {
129-
if reachable, err := p.isReachable(*(*url.URL)(desc.APIDocumentation)); !reachable {
129+
if network && desc.APIDocumentation != nil {
130+
if reachable, err := parser.isReachable(*(*url.URL)(desc.APIDocumentation), network); !reachable {
130131
vr = append(vr, newValidationError(
131132
fmt.Sprintf("description.%s.apiDocumentation", lang),
132133
"'%s' not reachable: %s", desc.APIDocumentation, err.Error(),
@@ -135,15 +136,15 @@ func (p *Parser) validateFields() error {
135136
}
136137

137138
for i, v := range desc.Screenshots {
138-
if isImage, err := p.isImageFile(p.toURL(v)); !isImage {
139+
if isImage, err := parser.isImageFile(toCodeHostingURL(v, parser.baseURL), network); !isImage {
139140
vr = append(vr, newValidationError(
140141
fmt.Sprintf("description.%s.screenshots[%d]", lang, i),
141142
"'%s' is not an image: %s", v, err.Error(),
142143
))
143144
}
144145
}
145146
for i, v := range desc.Videos {
146-
_, err := p.isOEmbedURL((*url.URL)(v))
147+
_, err := parser.isOEmbedURL((*url.URL)(v))
147148
if err != nil {
148149
vr = append(vr, newValidationError(
149150
fmt.Sprintf("description.%s.videos[%d]", lang, i),
@@ -159,3 +160,7 @@ func (p *Parser) validateFields() error {
159160

160161
return vr
161162
}
163+
164+
func validateFieldsV1(_ PublicCode, _ Parser, _ bool) error {
165+
return nil
166+
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/italia/publiccode-parser-go/v3
1+
module github.com/italia/publiccode-parser-go/v4
22

33
require (
44
github.com/alranel/go-vcsurl/v2 v2.0.2

0 commit comments

Comments
 (0)