Skip to content

Commit db7d9a2

Browse files
committed
Fix handling of prefixed @vocab
1 parent dff5ffb commit db7d9a2

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

lib/ContextParser.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -780,11 +780,17 @@ must be one of ${Util.CONTAINERS.join(', ')}`, ERROR_CODES.INVALID_CONTAINER_MAP
780780
// Parse inner contexts with minimal processing
781781
await this.parseInnerContexts(newContext, options);
782782

783-
// In JSON-LD 1.1, @vocab can be relative to @vocab in the parent context.
783+
// In JSON-LD 1.1, @vocab can be relative to @vocab in the parent context, or a compact IRI.
784784
if ((newContext && newContext['@version'] || ContextParser.DEFAULT_PROCESSING_MODE) >= 1.1
785-
&& ((context['@vocab'] && typeof context['@vocab'] === 'string') || context['@vocab'] === '')
786-
&& context['@vocab'].indexOf(':') < 0 && parentContext && '@vocab' in parentContext) {
787-
newContext['@vocab'] = parentContext['@vocab'] + context['@vocab'];
785+
&& ((context['@vocab'] && typeof context['@vocab'] === 'string') || context['@vocab'] === '')) {
786+
if (parentContext && '@vocab' in parentContext && context['@vocab'].indexOf(':') < 0) {
787+
newContext['@vocab'] = parentContext['@vocab'] + context['@vocab'];
788+
} else {
789+
if (Util.isCompactIri(context['@vocab']) || context['@vocab'] in newContextWrapped.getContextRaw()) {
790+
// @vocab is a compact IRI or refers exactly to a prefix
791+
newContext['@vocab'] = newContextWrapped.expandTerm(context['@vocab'], true);
792+
}
793+
}
788794
}
789795

790796
// Handle terms (before protection checks)

test/ContextParser-test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,36 @@ Tried mapping @id to {}`, ERROR_CODES.KEYWORD_REDEFINITION));
20432043
}));
20442044
});
20452045

2046+
it('should parse compact @vocab in 1.1', () => {
2047+
return expect(parser.parse({ '@vocab': 'ex:vocab/', '@version': 1.1, ex: {
2048+
'@id': 'http://example.org/',
2049+
'@prefix': true
2050+
}}, {}))
2051+
.resolves.toEqual(new JsonLdContextNormalized({
2052+
'@version': 1.1,
2053+
'@vocab': 'http://example.org/vocab/',
2054+
ex: {
2055+
'@id': 'http://example.org/',
2056+
'@prefix': true
2057+
},
2058+
}));
2059+
});
2060+
2061+
it('should parse compact @vocab in 1.1 that equals a prefix', () => {
2062+
return expect(parser.parse({ '@vocab': 'ex', '@version': 1.1, ex: {
2063+
'@id': 'http://example.org/',
2064+
'@prefix': true
2065+
}}, {}))
2066+
.resolves.toEqual(new JsonLdContextNormalized({
2067+
'@version': 1.1,
2068+
'@vocab': 'http://example.org/',
2069+
ex: {
2070+
'@id': 'http://example.org/',
2071+
'@prefix': true
2072+
},
2073+
}));
2074+
});
2075+
20462076
it('should not expand @type in @container: @type', () => {
20472077
return expect(parser.parse({
20482078
'@base': 'http://example.org/base/',

test/JsonLdContextNormalized-test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ describe('JsonLdContextNormalized', () => {
3030
expect(context.expandTerm('def:123', true)).toBe('def:123');
3131
});
3232

33+
it('to return when it is a prefix', async () => {
34+
const context = new JsonLdContextNormalized({def: 'http://DEF/'});
35+
expect(context.expandTerm('def', true)).toBe('http://DEF/');
36+
});
37+
38+
it('to return when it is a prefix with colon', async () => {
39+
const context = new JsonLdContextNormalized({def: 'DEF/'});
40+
expect(context.expandTerm('def:', true)).toBe('DEF/');
41+
});
42+
3343
it('to return when a direct value applies', async () => {
3444
const context = new JsonLdContextNormalized({abc: 'http://DEF'});
3545
expect(context.expandTerm('abc', true)).toBe('http://DEF');
@@ -647,6 +657,11 @@ describe('JsonLdContextNormalized', () => {
647657
expect(context.expandTerm('def:123', false)).toBe('def:123');
648658
});
649659

660+
it('to return when it is a prefix with colon', async () => {
661+
const context = new JsonLdContextNormalized({def: 'DEF/'});
662+
expect(context.expandTerm('def:', false)).toBe('DEF/');
663+
});
664+
650665
it('to return when a direct value applies, but ignore it in base-mode', async () => {
651666
const context = new JsonLdContextNormalized({abc: 'DEF'});
652667
expect(context.expandTerm('abc', false)).toBe('abc');

0 commit comments

Comments
 (0)