Skip to content

Commit 4ce1472

Browse files
gkelloggdavidlehn
authored andcommitted
In 1.0 mode, only consider terms ending in a delimiter for compact IRI prefixes. In 1.1 mode, also consider those with @prefix.
1 parent d51b9cb commit 4ce1472

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

lib/compact.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,14 +653,15 @@ api.compactIri = ({
653653
for(let i = partialMatches.length - 1; i >= 0; --i) {
654654
const entry = partialMatches[i];
655655
const terms = entry.terms;
656-
for(let ti = 0; ti < terms.length; ++ti) {
656+
for(let term of terms) {
657657
// a CURIE is usable if:
658658
// 1. it has no mapping, OR
659659
// 2. value is null, which means we're not compacting an @value, AND
660660
// the mapping matches the IRI
661-
const curie = terms[ti] + ':' + iri.substr(entry.iri.length);
662-
const isUsableCurie = (!(curie in activeCtx.mappings) ||
663-
(value === null && activeCtx.mappings[curie]['@id'] === iri));
661+
const curie = term + ':' + iri.substr(entry.iri.length);
662+
const isUsableCurie = (activeCtx.mappings[term]._prefix &&
663+
(!(curie in activeCtx.mappings) ||
664+
(value === null && activeCtx.mappings[curie]['@id'] === iri)));
664665

665666
// select curie if it is shorter or the same length but lexicographically
666667
// less than the current choice

lib/context.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
240240
}
241241

242242
// convert short-hand value to object w/@id
243+
let simpleTerm = false;
243244
if(_isString(value)) {
245+
simpleTerm = true;
244246
value = {'@id': value};
245247
}
246248

@@ -261,7 +263,7 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
261263

262264
// JSON-LD 1.1 support
263265
if(api.processingMode(activeCtx, 1.1)) {
264-
validKeys.push('@context');
266+
validKeys.push('@context', '@prefix');
265267
}
266268

267269
for(let kw in value) {
@@ -273,6 +275,11 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
273275
}
274276
}
275277

278+
// always compute whether term has a colon as an optimization for
279+
// _compactIri
280+
const colon = term.indexOf(':');
281+
mapping._termHasColon = (colon !== -1);
282+
276283
if('@reverse' in value) {
277284
if('@id' in value) {
278285
throw new JsonLdError(
@@ -318,14 +325,13 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
318325
{code: 'invalid IRI mapping', context: localCtx});
319326
}
320327
mapping['@id'] = id;
328+
// indicate if this term may be used as a compact IRI prefix
329+
mapping._prefix = (!mapping._termHasColon &&
330+
id.match(/[:\/\?#\[\]@]$/) &&
331+
(simpleTerm || !activeCtx.processingMode || activeCtx.processingMode == 'json-ld-1.0'));
321332
}
322333
}
323334

324-
// always compute whether term has a colon as an optimization for
325-
// _compactIri
326-
const colon = term.indexOf(':');
327-
mapping._termHasColon = (colon !== -1);
328-
329335
if(!('@id' in mapping)) {
330336
// see if the term has a prefix
331337
if(mapping._termHasColon) {
@@ -478,6 +484,24 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => {
478484
mapping['@language'] = language;
479485
}
480486

487+
// term may be used as a prefix
488+
if('@prefix' in value) {
489+
if(mapping._termHasColon) {
490+
throw new JsonLdError(
491+
'Invalid JSON-LD syntax; @context @prefix used on a compact IRI term',
492+
'jsonld.SyntaxError',
493+
{code: 'invalid term definition', context: localCtx});
494+
}
495+
if(value['@prefix'] === true || value['@prefix'] === false) {
496+
mapping._prefix = value['@prefix'] === true
497+
} else {
498+
throw new JsonLdError(
499+
'Invalid JSON-LD syntax; @context value for @prefix must be boolean',
500+
'jsonld.SyntaxError',
501+
{code: 'invalid @prefix value', context: localCtx});
502+
}
503+
}
504+
481505
// disallow aliasing @context and @preserve
482506
const id = mapping['@id'];
483507
if(id === '@context' || id === '@preserve') {
@@ -861,6 +885,7 @@ api.isKeyword = v => {
861885
case '@list':
862886
case '@none':
863887
case '@omitDefault':
888+
case '@prefix':
864889
case '@preserve':
865890
case '@requireAll':
866891
case '@reverse':

tests/test-common.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const manifest = options.manifest || {
2929
const TEST_TYPES = {
3030
'jld:CompactTest': {
3131
skip: {
32-
regex: [/#t0073/, /#t[anp]/]
32+
specVersion: ['json-ld-1.0'],
33+
regex: [/#t0073/, /#t[n]/]
3334
},
3435
fn: 'compact',
3536
params: [

0 commit comments

Comments
 (0)