@@ -8,6 +8,7 @@ const JsonLdError = require('./JsonLdError');
8
8
const {
9
9
isArray : _isArray ,
10
10
isObject : _isObject ,
11
+ isEmptyObject : _isEmptyObject ,
11
12
isString : _isString
12
13
} = require ( './types' ) ;
13
14
@@ -31,7 +32,8 @@ const {
31
32
32
33
const {
33
34
addValue : _addValue ,
34
- validateTypeValue : _validateTypeValue
35
+ validateTypeValue : _validateTypeValue ,
36
+ getValues : _getValues
35
37
} = require ( './util' ) ;
36
38
37
39
const api = { } ;
@@ -206,8 +208,11 @@ api.expand = ({
206
208
'which can be "@type" or "@language".' ,
207
209
'jsonld.SyntaxError' , { code : 'invalid value object' , element : rval } ) ;
208
210
}
211
+ const values = rval [ '@value' ] === null ? [ ] : [ ] . concat ( rval [ '@value' ] ) ;
212
+ const types = _getValues ( rval , '@type' ) ;
213
+
209
214
// drop null @values unless custom mapped
210
- if ( rval [ '@value' ] === null ) {
215
+ if ( values . length === 0 ) {
211
216
// TODO: use `await` to support async
212
217
const mapped = expansionMap ( {
213
218
unmappedValue : rval ,
@@ -222,15 +227,16 @@ api.expand = ({
222
227
} else {
223
228
rval = null ;
224
229
}
225
- } else if ( '@language' in rval && ! _isString ( rval [ '@value' ] ) ) {
230
+ } else if ( ! values . every ( v => ( _isString ( v ) || _isEmptyObject ( v ) ) ) && '@language' in rval ) {
226
231
// if @language is present, @value must be a string
227
232
throw new JsonLdError (
228
233
'Invalid JSON-LD syntax; only strings may be language-tagged.' ,
229
234
'jsonld.SyntaxError' ,
230
235
{ code : 'invalid language-tagged value' , element : rval } ) ;
231
- } else if ( '@type' in rval && ( ! _isAbsoluteIri ( rval [ '@type' ] ) ||
232
- rval [ '@type' ] . indexOf ( '_:' ) === 0 ) ) {
233
- throw new JsonLdError (
236
+ } else if ( ! types . every ( t =>
237
+ ( _isAbsoluteIri ( t ) && ! ( _isString ( t ) && t . indexOf ( '_:' ) === 0 ) ||
238
+ _isEmptyObject ( t ) ) ) ) {
239
+ throw new JsonLdError (
234
240
'Invalid JSON-LD syntax; an element containing "@value" and "@type" ' +
235
241
'must have an absolute IRI for the value of "@type".' ,
236
242
'jsonld.SyntaxError' , { code : 'invalid typed value' , element : rval } ) ;
@@ -373,22 +379,50 @@ function _expandObject({
373
379
}
374
380
375
381
// syntax error if @id is not a string
376
- if ( expandedProperty === '@id' && ! _isString ( value ) ) {
377
- if ( ! options . isFrame ) {
378
- throw new JsonLdError (
379
- 'Invalid JSON-LD syntax; "@id" value must a string.' ,
380
- 'jsonld.SyntaxError' , { code : 'invalid @id value' , value : value } ) ;
381
- }
382
- if ( ! _isObject ( value ) ) {
383
- throw new JsonLdError (
384
- 'Invalid JSON-LD syntax; "@id" value must be a string or an ' +
385
- 'object.' , 'jsonld.SyntaxError' ,
386
- { code : 'invalid @id value' , value : value } ) ;
382
+ if ( expandedProperty === '@id' ) {
383
+ if ( ! _isString ( value ) ) {
384
+ if ( ! options . isFrame ) {
385
+ throw new JsonLdError (
386
+ 'Invalid JSON-LD syntax; "@id" value must a string.' ,
387
+ 'jsonld.SyntaxError' , { code : 'invalid @id value' , value : value } ) ;
388
+ }
389
+ if ( _isObject ( value ) ) {
390
+ // empty object is a wildcard
391
+ if ( ! _isEmptyObject ( value ) ) {
392
+ throw new JsonLdError (
393
+ 'Invalid JSON-LD syntax; "@id" value an empty object or array of strings, if framing' ,
394
+ 'jsonld.SyntaxError' , { code : 'invalid @id value' , value : value } ) ;
395
+ }
396
+ } else if ( _isArray ( value ) ) {
397
+ if ( ! value . every ( v => _isString ( v ) ) ) {
398
+ throw new JsonLdError (
399
+ 'Invalid JSON-LD syntax; "@id" value an empty object or array of strings, if framing' ,
400
+ 'jsonld.SyntaxError' , { code : 'invalid @id value' , value : value } ) ;
401
+ }
402
+ } else {
403
+ throw new JsonLdError (
404
+ 'Invalid JSON-LD syntax; "@id" value an empty object or array of strings, if framing' ,
405
+ 'jsonld.SyntaxError' , { code : 'invalid @id value' , value : value } ) ;
406
+ }
387
407
}
408
+
409
+ _addValue (
410
+ expandedParent , '@id' ,
411
+ [ ] . concat ( value ) . map ( v => _isString ( v ) ? _expandIri ( activeCtx , v , { base : true } ) : v ) ,
412
+ { propertyIsArray : options . isFrame } ) ;
413
+ continue ;
388
414
}
389
415
390
416
if ( expandedProperty === '@type' ) {
391
417
_validateTypeValue ( value ) ;
418
+ _addValue (
419
+ expandedParent , '@type' ,
420
+ [ ] . concat ( value ) . map ( v =>
421
+ _isString ( v ) ?
422
+ _expandIri ( activeCtx , v , { base : true , vocab : true } ) :
423
+ v ) ,
424
+ { propertyIsArray : options . isFrame } ) ;
425
+ continue ;
392
426
}
393
427
394
428
// @graph must be an array or an object
@@ -400,14 +434,19 @@ function _expandObject({
400
434
'jsonld.SyntaxError' , { code : 'invalid @graph value' , value : value } ) ;
401
435
}
402
436
403
- // @value must not be an object or an array
404
- if ( expandedProperty === '@value' &&
405
- ( _isObject ( value ) || _isArray ( value ) ) ) {
406
- throw new JsonLdError (
407
- 'Invalid JSON-LD syntax; "@value" value must not be an ' +
408
- 'object or an array.' ,
409
- 'jsonld.SyntaxError' ,
410
- { code : 'invalid value object value' , value : value } ) ;
437
+ // @value must not be an object or an array (unless framing)
438
+ if ( expandedProperty === '@value' ) {
439
+ if ( ( _isObject ( value ) || _isArray ( value ) ) && ! options . isFrame ) {
440
+ throw new JsonLdError (
441
+ 'Invalid JSON-LD syntax; "@value" value must not be an ' +
442
+ 'object or an array.' ,
443
+ 'jsonld.SyntaxError' ,
444
+ { code : 'invalid value object value' , value : value } ) ;
445
+ }
446
+
447
+ _addValue (
448
+ expandedParent , '@value' , value , { propertyIsArray : options . isFrame } ) ;
449
+ continue ;
411
450
}
412
451
413
452
// @language must be a string
@@ -416,14 +455,18 @@ function _expandObject({
416
455
// drop null @language values, they expand as if they didn't exist
417
456
continue ;
418
457
}
419
- if ( ! _isString ( value ) ) {
458
+ if ( ! _isString ( value ) && ! options . isFrame ) {
420
459
throw new JsonLdError (
421
460
'Invalid JSON-LD syntax; "@language" value must be a string.' ,
422
461
'jsonld.SyntaxError' ,
423
462
{ code : 'invalid language-tagged string' , value : value } ) ;
424
463
}
425
464
// ensure language value is lowercase
426
465
value = value . toLowerCase ( ) ;
466
+
467
+ _addValue (
468
+ expandedParent , '@language' , value , { propertyIsArray : options . isFrame } ) ;
469
+ continue ;
427
470
}
428
471
429
472
// @index must be a string
@@ -434,6 +477,8 @@ function _expandObject({
434
477
'jsonld.SyntaxError' ,
435
478
{ code : 'invalid @index value' , value : value } ) ;
436
479
}
480
+ _addValue ( expandedParent , '@index' , value ) ;
481
+ continue ;
437
482
}
438
483
439
484
// @reverse must be an object
0 commit comments