@@ -70,12 +70,33 @@ api.process = ({activeCtx, localCtx, options,
70
70
// We can't nullify if there are protected terms and we're
71
71
// not in a term definition
72
72
if ( ! propertyTermDefinition &&
73
- Object . keys ( activeCtx . protected ) . length !== 0 ) {
73
+ Object . keys ( activeCtx . protected ) . length !== 0 ) {
74
+ const protectedMode = ( options && options . protectedMode ) || 'error' ;
75
+ if ( protectedMode === 'error' ) {
76
+ throw new JsonLdError (
77
+ 'Tried to nullify a context with protected terms outside of ' +
78
+ 'a term definition.' ,
79
+ 'jsonld.SyntaxError' ,
80
+ { code : 'invalid context nullification' } ) ;
81
+ } else if ( protectedMode === 'warn' ) {
82
+ // FIXME: remove logging and use a handler
83
+ console . warn ( 'WARNING: invalid context nullification' ) ;
84
+ const oldActiveCtx = activeCtx ;
85
+ rval = activeCtx = api . getInitialContext ( options ) ;
86
+ for ( const [ term , _protected ] of
87
+ Object . entries ( oldActiveCtx . protected ) ) {
88
+ if ( _protected ) {
89
+ activeCtx . mappings [ term ] =
90
+ util . clone ( oldActiveCtx . mappings [ term ] ) ;
91
+ }
92
+ }
93
+ activeCtx . protected = util . clone ( oldActiveCtx . protected ) ;
94
+ continue ;
95
+ }
74
96
throw new JsonLdError (
75
- 'Tried to nullify a context with protected terms outside of ' +
76
- 'a term definition.' ,
97
+ 'Invalid protectedMode.' ,
77
98
'jsonld.SyntaxError' ,
78
- { code : 'invalid context nullification' } ) ;
99
+ { code : 'invalid protected mode' , context : localCtx , protectedMode } ) ;
79
100
}
80
101
rval = activeCtx = api . getInitialContext ( options ) ;
81
102
continue ;
@@ -200,7 +221,7 @@ api.process = ({activeCtx, localCtx, options,
200
221
201
222
// process all other keys
202
223
for ( const key in ctx ) {
203
- api . createTermDefinition ( rval , ctx , key , defined ) ;
224
+ api . createTermDefinition ( rval , ctx , key , defined , options ) ;
204
225
}
205
226
206
227
// cache result
@@ -220,8 +241,12 @@ api.process = ({activeCtx, localCtx, options,
220
241
* @param term the term in the local context to define the mapping for.
221
242
* @param defined a map of defining/defined keys to detect cycles and prevent
222
243
* double definitions.
244
+ * @param {Object } [options] - creation options.
245
+ * @param {string } [options.protectedMode="error"] - "error" to throw error
246
+ * on `@protected` constraint violation, "warn" to allow violations and
247
+ * signal a warning.
223
248
*/
224
- api . createTermDefinition = ( activeCtx , localCtx , term , defined ) => {
249
+ api . createTermDefinition = ( activeCtx , localCtx , term , defined , options ) => {
225
250
if ( term in defined ) {
226
251
// term already defined
227
252
if ( defined [ term ] ) {
@@ -251,11 +276,24 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
251
276
{ code : 'invalid term definition' , context : localCtx } ) ;
252
277
}
253
278
254
- if ( activeCtx . protected [ term ] ) {
279
+ // FIXME if(1.1) ... ?
280
+ if ( term in activeCtx . protected ) {
281
+ const protectedMode = ( options && options . protectedMode ) || 'error' ;
282
+ if ( protectedMode === 'error' ) {
283
+ throw new JsonLdError (
284
+ 'Invalid JSON-LD syntax; tried to redefine a protected term.' ,
285
+ 'jsonld.SyntaxError' ,
286
+ { code : 'protected term redefinition' , context : localCtx , term} ) ;
287
+ } else if ( protectedMode === 'warn' ) {
288
+ // FIXME: remove logging and use a handler
289
+ console . warn ( 'WARNING: protected term redefinition' , { term} ) ;
290
+ return ;
291
+ }
255
292
throw new JsonLdError (
256
- 'Invalid JSON-LD syntax; tried to redefine a protected term .' ,
293
+ 'Invalid protectedMode .' ,
257
294
'jsonld.SyntaxError' ,
258
- { code : 'protected term redefinition' , context : localCtx , term} ) ;
295
+ { code : 'invalid protected mode' , context : localCtx , term,
296
+ protectedMode} ) ;
259
297
}
260
298
261
299
// remove old mapping
@@ -335,8 +373,9 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
335
373
}
336
374
337
375
// expand and add @id mapping
338
- const id = api . expandIri (
339
- activeCtx , reverse , { vocab : true , base : false } , localCtx , defined ) ;
376
+ const id = _expandIri (
377
+ activeCtx , reverse , { vocab : true , base : false } , localCtx , defined ,
378
+ options ) ;
340
379
if ( ! _isAbsoluteIri ( id ) ) {
341
380
throw new JsonLdError (
342
381
'Invalid JSON-LD syntax; a @context @reverse value must be an ' +
@@ -355,8 +394,8 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
355
394
}
356
395
if ( id !== term ) {
357
396
// expand and add @id mapping
358
- id = api . expandIri (
359
- activeCtx , id , { vocab : true , base : false } , localCtx , defined ) ;
397
+ id = _expandIri (
398
+ activeCtx , id , { vocab : true , base : false } , localCtx , defined , options ) ;
360
399
if ( ! _isAbsoluteIri ( id ) && ! api . isKeyword ( id ) ) {
361
400
throw new JsonLdError (
362
401
'Invalid JSON-LD syntax; a @context @id value must be an ' +
@@ -378,7 +417,7 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
378
417
const prefix = term . substr ( 0 , colon ) ;
379
418
if ( prefix in localCtx ) {
380
419
// define parent prefix
381
- api . createTermDefinition ( activeCtx , localCtx , prefix , defined ) ;
420
+ api . createTermDefinition ( activeCtx , localCtx , prefix , defined , options ) ;
382
421
}
383
422
384
423
if ( activeCtx . mappings [ prefix ] ) {
@@ -427,8 +466,9 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
427
466
428
467
if ( type !== '@id' && type !== '@vocab' ) {
429
468
// expand @type to full IRI
430
- type = api . expandIri (
431
- activeCtx , type , { vocab : true , base : false } , localCtx , defined ) ;
469
+ type = _expandIri (
470
+ activeCtx , type , { vocab : true , base : false } , localCtx , defined ,
471
+ options ) ;
432
472
if ( ! _isAbsoluteIri ( type ) ) {
433
473
throw new JsonLdError (
434
474
'Invalid JSON-LD syntax; an @context @type value must be an ' +
@@ -579,6 +619,25 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
579
619
}
580
620
} ;
581
621
622
+ /**
623
+ * Expands a string to a full IRI. The string may be a term, a prefix, a
624
+ * relative IRI, or an absolute IRI. The associated absolute IRI will be
625
+ * returned.
626
+ *
627
+ * @param activeCtx the current active context.
628
+ * @param value the string to expand.
629
+ * @param relativeTo options for how to resolve relative IRIs:
630
+ * base: true to resolve against the base IRI, false not to.
631
+ * vocab: true to concatenate after @vocab, false not to.
632
+ * @param {Object } [options] - processing options.
633
+ *
634
+ * @return the expanded value.
635
+ */
636
+ api . expandIri = ( activeCtx , value , relativeTo , options ) => {
637
+ return _expandIri ( activeCtx , value , relativeTo , undefined , undefined ,
638
+ options ) ;
639
+ } ;
640
+
582
641
/**
583
642
* Expands a string to a full IRI. The string may be a term, a prefix, a
584
643
* relative IRI, or an absolute IRI. The associated absolute IRI will be
@@ -593,18 +652,19 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
593
652
* during context processing).
594
653
* @param defined a map for tracking cycles in context definitions (only given
595
654
* if called during context processing).
655
+ * @param {Object } [options] - processing options.
596
656
*
597
657
* @return the expanded value.
598
658
*/
599
- api . expandIri = ( activeCtx , value , relativeTo , localCtx , defined ) => {
659
+ function _expandIri ( activeCtx , value , relativeTo , localCtx , defined , options ) {
600
660
// already expanded
601
661
if ( value === null || ! _isString ( value ) || api . isKeyword ( value ) ) {
602
662
return value ;
603
663
}
604
664
605
665
// define term dependency if not defined
606
666
if ( localCtx && value in localCtx && defined [ value ] !== true ) {
607
- api . createTermDefinition ( activeCtx , localCtx , value , defined ) ;
667
+ api . createTermDefinition ( activeCtx , localCtx , value , defined , options ) ;
608
668
}
609
669
610
670
relativeTo = relativeTo || { } ;
@@ -636,7 +696,7 @@ api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => {
636
696
637
697
// prefix dependency not defined, define it
638
698
if ( localCtx && prefix in localCtx ) {
639
- api . createTermDefinition ( activeCtx , localCtx , prefix , defined ) ;
699
+ api . createTermDefinition ( activeCtx , localCtx , prefix , defined , options ) ;
640
700
}
641
701
642
702
// use mapping if prefix is defined
@@ -660,7 +720,7 @@ api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => {
660
720
}
661
721
662
722
return value ;
663
- } ;
723
+ }
664
724
665
725
/**
666
726
* Gets the initial context.
0 commit comments