From 10d7e48c489f3d5fcaa59015a4f409ee31047ba1 Mon Sep 17 00:00:00 2001 From: Ruben Taelman Date: Wed, 23 Oct 2024 15:38:12 +0200 Subject: [PATCH] Support @json ranges in arrays --- lib/serialize/ContextConstructor.ts | 10 +++- test/serialize/ContextConstructor.test.ts | 70 +++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/lib/serialize/ContextConstructor.ts b/lib/serialize/ContextConstructor.ts index 0c89807..67ed3c4 100644 --- a/lib/serialize/ContextConstructor.ts +++ b/lib/serialize/ContextConstructor.ts @@ -72,7 +72,7 @@ export class ContextConstructor { const shortcut = parameter['@id'].slice(Math.max(0, component['@id'].length + 1)); typeScopedContext[shortcut] = { '@id': parameter['@id'], - ...parameter.range === 'rdf:JSON' ? { '@type': '@json' } : {}, + ...ContextConstructor.isParameterRangeJson(parameter.range) ? { '@type': '@json' } : {}, // Mark as list container if range is array ...ContextConstructor.isParameterRangeList(parameter.range) ? { '@container': '@list' } : @@ -133,6 +133,14 @@ export class ContextConstructor { public static isParameterRangeUndefined(range: ParameterDefinitionRange): boolean { return typeof range !== 'string' && '@type' in range && range['@type'] === 'ParameterRangeUndefined'; } + + public static isParameterRangeJson(range: ParameterDefinitionRange | undefined): boolean { + if (range && typeof range !== 'string' && '@type' in range && + range['@type'] === 'ParameterRangeArray' && this.isParameterRangeJson(range.parameterRangeValue)) { + return true; + } + return range === 'rdf:JSON'; + } } export interface ContextConstructorArgs { diff --git a/test/serialize/ContextConstructor.test.ts b/test/serialize/ContextConstructor.test.ts index f813756..11e2fe4 100644 --- a/test/serialize/ContextConstructor.test.ts +++ b/test/serialize/ContextConstructor.test.ts @@ -612,6 +612,76 @@ describe('ContextConstructor', () => { }); }); + it('should handle non-empty component definitions for JSON ranges in arrays', () => { + expect(ctor.constructComponentShortcuts({ + '/docs/package/components/file1': { + '@context': [ + 'https://linkedsoftwaredependencies.org/bundles/npm/my-package/context.jsonld', + ], + '@id': 'npmd:my-package', + components: [ + { + '@id': 'mp:file1#MyClass1', + '@type': 'Class', + constructorArguments: [], + parameters: [ + { + '@id': 'mp:file1#MyClass1_param1', + range: { + '@type': 'ParameterRangeArray', + parameterRangeValue: 'rdf:JSON', + }, + }, + { + '@id': 'mp:file1#MyClass1_param2', + range: 'rdf:JSON', + }, + ], + memberFields: [], + requireElement: 'MyClass1', + }, + ], + }, + '/docs/package/components/b/file2': { + '@context': [ + 'https://linkedsoftwaredependencies.org/bundles/npm/my-package/context.jsonld', + ], + '@id': 'npmd:my-package', + components: [ + { + '@id': 'mp:b/file2#MyClass2', + '@type': 'Class', + requireElement: 'MyClass2', + constructorArguments: [], + parameters: [], + memberFields: [], + }, + ], + }, + })).toEqual({ + MyClass1: { + '@id': 'mp:file1#MyClass1', + '@prefix': true, + '@context': { + param1: { + '@id': 'mp:file1#MyClass1_param1', + '@type': '@json', + '@container': '@list', + }, + param2: { + '@id': 'mp:file1#MyClass1_param2', + '@type': '@json', + }, + }, + }, + MyClass2: { + '@id': 'mp:b/file2#MyClass2', + '@prefix': true, + '@context': {}, + }, + }); + }); + it('should handle non-empty component definitions when typeScopedContexts is true for opt arrays', () => { ctor = new ContextConstructor({ packageMetadata,