@@ -255,9 +255,38 @@ const PurlType = createHelpersNamespaceObject(
255255 } ,
256256 } ,
257257 validate : {
258- // TODO: cocoapods name validation
259- // TODO: cpan namespace validation
260- // TODO: swid qualifier validation
258+ // https://github.com/package-url/purl-spec/blob/master/types-doc/cocoapods-definition.md
259+ cocoapods ( purl : PurlObject , throws : boolean ) {
260+ const { name } = purl
261+ // Name cannot contain whitespace.
262+ if ( / \s / . test ( name ) ) {
263+ if ( throws ) {
264+ throw new PurlError (
265+ 'cocoapods "name" component cannot contain whitespace' ,
266+ )
267+ }
268+ return false
269+ }
270+ // Name cannot contain a plus (+) character.
271+ if ( name . includes ( '+' ) ) {
272+ if ( throws ) {
273+ throw new PurlError (
274+ 'cocoapods "name" component cannot contain a plus (+) character' ,
275+ )
276+ }
277+ return false
278+ }
279+ // Name cannot begin with a period (.).
280+ if ( name . charCodeAt ( 0 ) === 46 /*'.'*/ ) {
281+ if ( throws ) {
282+ throw new PurlError (
283+ 'cocoapods "name" component cannot begin with a period' ,
284+ )
285+ }
286+ return false
287+ }
288+ return true
289+ } ,
261290 // https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#conan
262291 conan ( purl : PurlObject , throws : boolean ) {
263292 if ( isNullishOrEmptyString ( purl . namespace ) ) {
@@ -279,6 +308,18 @@ const PurlType = createHelpersNamespaceObject(
279308 }
280309 return true
281310 } ,
311+ // https://github.com/package-url/purl-spec/blob/master/types-doc/cpan-definition.md
312+ cpan ( purl : PurlObject , throws : boolean ) {
313+ // CPAN namespace (author/publisher ID) must be uppercase when present.
314+ const { namespace } = purl
315+ if ( namespace && namespace !== namespace . toUpperCase ( ) ) {
316+ if ( throws ) {
317+ throw new PurlError ( 'cpan "namespace" component must be UPPERCASE' )
318+ }
319+ return false
320+ }
321+ return true
322+ } ,
282323 // https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#cran
283324 cran ( purl : PurlObject , throws : boolean ) {
284325 return validateRequiredByType ( 'cran' , 'version' , purl . version , throws )
@@ -480,6 +521,40 @@ const PurlType = createHelpersNamespaceObject(
480521 }
481522 return true
482523 } ,
524+ // https://github.com/package-url/purl-spec/blob/master/types-doc/swid-definition.md
525+ swid ( purl : PurlObject , throws : boolean ) {
526+ const { qualifiers } = purl
527+ // SWID requires a tag_id qualifier.
528+ const tagId = qualifiers ?. [ 'tag_id' ]
529+ if ( ! tagId ) {
530+ if ( throws ) {
531+ throw new PurlError ( 'swid requires a "tag_id" qualifier' )
532+ }
533+ return false
534+ }
535+ // tag_id must not be empty after trimming.
536+ const tagIdStr = String ( tagId ) . trim ( )
537+ if ( tagIdStr . length === 0 ) {
538+ if ( throws ) {
539+ throw new PurlError ( 'swid "tag_id" qualifier must not be empty' )
540+ }
541+ return false
542+ }
543+ // If tag_id is a GUID, it must be lowercase.
544+ const guidPattern =
545+ / ^ [ 0 - 9 a - f ] { 8 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 12 } $ / i
546+ if ( guidPattern . test ( tagIdStr ) ) {
547+ if ( tagIdStr !== tagIdStr . toLowerCase ( ) ) {
548+ if ( throws ) {
549+ throw new PurlError (
550+ 'swid "tag_id" qualifier must be lowercase when it is a GUID' ,
551+ )
552+ }
553+ return false
554+ }
555+ }
556+ return true
557+ } ,
483558 // https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#swift
484559 swift ( purl : PurlObject , throws : boolean ) {
485560 return (
0 commit comments