diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8517aa..3ce3d138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added - Testing: `skip` and `only` flags in manifests. - Testing: `VERBOSE_SKIP=true` env var to debug skipping. +- Support `@protected` and `protectedMode`. ## 1.5.4 - 2019-02-28 diff --git a/lib/compact.js b/lib/compact.js index 0a54afa5..7b994100 100644 --- a/lib/compact.js +++ b/lib/compact.js @@ -8,7 +8,8 @@ const JsonLdError = require('./JsonLdError'); const { isArray: _isArray, isObject: _isObject, - isString: _isString + isString: _isString, + isUndefined: _isUndefined } = require('./types'); const { @@ -100,8 +101,13 @@ api.compact = ({ // use any scoped context on activeProperty const ctx = _getContextValue(activeCtx, activeProperty, '@context'); - if(ctx) { - activeCtx = _processContext({activeCtx, localCtx: ctx, options}); + if(!_isUndefined(ctx)) { + // Note: spec's `from term` var is named `isPropertyTermScopedContext` + activeCtx = _processContext({ + activeCtx, + localCtx: ctx, + options: {...options, isPropertyTermScopedContext: true} + }); } // recursively compact object @@ -119,7 +125,7 @@ api.compact = ({ // do value compaction on @values and subject references if(_isValue(element) || _isSubjectReference(element)) { const rval = - api.compactValue({activeCtx, activeProperty, value: element}); + api.compactValue({activeCtx, activeProperty, value: element, options}); if(options.link && _isSubjectReference(element)) { // store linked element if(!(element['@id'] in options.link)) { @@ -156,7 +162,7 @@ api.compact = ({ // Use any scoped context defined on this value const ctx = _getContextValue(activeCtx, compactedType, '@context'); - if(ctx) { + if(!_isUndefined(ctx)) { activeCtx = _processContext({activeCtx, localCtx: ctx, options}); } } @@ -294,7 +300,7 @@ api.compact = ({ activeCtx.mappings[itemActiveProperty]['@nest'] : null; let nestResult = rval; if(nestProperty) { - _checkNestProperty(activeCtx, nestProperty); + _checkNestProperty(activeCtx, nestProperty, options); if(!_isObject(rval[nestProperty])) { rval[nestProperty] = {}; } @@ -323,7 +329,7 @@ api.compact = ({ activeCtx.mappings[itemActiveProperty]['@nest'] : null; let nestResult = rval; if(nestProperty) { - _checkNestProperty(activeCtx, nestProperty); + _checkNestProperty(activeCtx, nestProperty, options); if(!_isObject(rval[nestProperty])) { rval[nestProperty] = {}; } @@ -794,10 +800,11 @@ api.compactIri = ({ * @param activeCtx the active context. * @param activeProperty the active property that points to the value. * @param value the value to compact. + * @param {Object} [options] - processing options. * * @return the compaction result. */ -api.compactValue = ({activeCtx, activeProperty, value}) => { +api.compactValue = ({activeCtx, activeProperty, value, options}) => { // value is a @value if(_isValue(value)) { // get context rules @@ -872,7 +879,8 @@ api.compactValue = ({activeCtx, activeProperty, value}) => { } // value is a subject reference - const expandedProperty = _expandIri(activeCtx, activeProperty, {vocab: true}); + const expandedProperty = _expandIri(activeCtx, activeProperty, {vocab: true}, + options); const type = _getContextValue(activeCtx, activeProperty, '@type'); const compacted = api.compactIri( {activeCtx, iri: value['@id'], relativeTo: {vocab: type === '@vocab'}}); @@ -1055,9 +1063,10 @@ function _selectTerm( * * @param activeCtx the active context. * @param nestProperty a term in the active context or `@nest`. + * @param {Object} [options] - processing options. */ -function _checkNestProperty(activeCtx, nestProperty) { - if(_expandIri(activeCtx, nestProperty, {vocab: true}) !== '@nest') { +function _checkNestProperty(activeCtx, nestProperty, options) { + if(_expandIri(activeCtx, nestProperty, {vocab: true}, options) !== '@nest') { throw new JsonLdError( 'JSON-LD compact error; nested property must have an @nest value ' + 'resolving to @nest.', diff --git a/lib/context.js b/lib/context.js index 6d640be8..f8c6e5f5 100644 --- a/lib/context.js +++ b/lib/context.js @@ -51,7 +51,7 @@ api.process = ({activeCtx, localCtx, options}) => { _isArray(localCtx['@context'])) { localCtx = localCtx['@context']; } - const ctxs = _isArray(localCtx) ? localCtx : [localCtx]; + const ctxs = _asArray(localCtx); // no contexts in array, return current active context w/o changes if(ctxs.length === 0) { @@ -64,8 +64,58 @@ api.process = ({activeCtx, localCtx, options}) => { for(let i = 0; i < ctxs.length; ++i) { let ctx = ctxs[i]; + // update active context to one computed from last iteration + activeCtx = rval; + + // get context from cache if available + if(api.cache) { + const cached = api.cache.get(activeCtx, ctx); + if(cached) { + rval = activeCtx = cached; + continue; + } + } + // reset to initial context if(ctx === null) { + // We can't nullify if there are protected terms and we're + // not processing a property term scoped context + if(!options.isPropertyTermScopedContext && + Object.keys(activeCtx.protected).length !== 0) { + const protectedMode = (options && options.protectedMode) || 'error'; + if(protectedMode === 'error') { + throw new JsonLdError( + 'Tried to nullify a context with protected terms outside of ' + + 'a term definition.', + 'jsonld.SyntaxError', + {code: 'invalid context nullification'}); + } else if(protectedMode === 'warn') { + // FIXME: remove logging and use a handler + console.warn('WARNING: invalid context nullification'); + const oldActiveCtx = activeCtx; + // copy all protected term definitions to fresh initial context + rval = activeCtx = api.getInitialContext(options); + for(const [term, _protected] of + Object.entries(oldActiveCtx.protected)) { + if(_protected) { + activeCtx.mappings[term] = + util.clone(oldActiveCtx.mappings[term]); + } + } + activeCtx.protected = util.clone(oldActiveCtx.protected); + + // cache result + if(api.cache) { + api.cache.set(oldActiveCtx, ctx, rval); + } + + continue; + } + throw new JsonLdError( + 'Invalid protectedMode.', + 'jsonld.SyntaxError', + {code: 'invalid protected mode', context: localCtx, protectedMode}); + } rval = activeCtx = api.getInitialContext(options); continue; } @@ -82,17 +132,7 @@ api.process = ({activeCtx, localCtx, options}) => { 'jsonld.SyntaxError', {code: 'invalid local context', context: ctx}); } - // get context from cache if available - if(api.cache) { - const cached = api.cache.get(activeCtx, ctx); - if(cached) { - rval = activeCtx = cached; - continue; - } - } - - // update active context and clone new one before updating - activeCtx = rval; + // clone context before updating it rval = rval.clone(); // define context mappings for keys in local context @@ -182,9 +222,14 @@ api.process = ({activeCtx, localCtx, options}) => { defined['@language'] = true; } + // handle @protected; determine whether this sub-context is declaring + // all its terms to be "protected" (exceptions can be made on a + // per-definition basis) + defined['@protected'] = ctx['@protected'] || false; + // process all other keys for(const key in ctx) { - api.createTermDefinition(rval, ctx, key, defined); + api.createTermDefinition(rval, ctx, key, defined, options); } // cache result @@ -204,8 +249,12 @@ api.process = ({activeCtx, localCtx, options}) => { * @param term the term in the local context to define the mapping for. * @param defined a map of defining/defined keys to detect cycles and prevent * double definitions. + * @param {Object} [options] - creation options. + * @param {string} [options.protectedMode="error"] - "error" to throw error + * on `@protected` constraint violation, "warn" to allow violations and + * signal a warning. */ -api.createTermDefinition = (activeCtx, localCtx, term, defined) => { +api.createTermDefinition = (activeCtx, localCtx, term, defined, options) => { if(term in defined) { // term already defined if(defined[term]) { @@ -235,6 +284,26 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { {code: 'invalid term definition', context: localCtx}); } + // FIXME if(1.1) ... ? + if(term in activeCtx.protected && !options.isPropertyTermScopedContext) { + const protectedMode = (options && options.protectedMode) || 'error'; + if(protectedMode === 'error') { + throw new JsonLdError( + 'Invalid JSON-LD syntax; tried to redefine a protected term.', + 'jsonld.SyntaxError', + {code: 'protected term redefinition', context: localCtx, term}); + } else if(protectedMode === 'warn') { + // FIXME: remove logging and use a handler + console.warn('WARNING: protected term redefinition', {term}); + return; + } + throw new JsonLdError( + 'Invalid protectedMode.', + 'jsonld.SyntaxError', + {code: 'invalid protected mode', context: localCtx, term, + protectedMode}); + } + // remove old mapping if(activeCtx.mappings[term]) { delete activeCtx.mappings[term]; @@ -274,7 +343,7 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { // JSON-LD 1.1 support if(api.processingMode(activeCtx, 1.1)) { - validKeys.push('@context', '@nest', '@prefix'); + validKeys.push('@context', '@nest', '@prefix', '@protected'); } for(const kw in value) { @@ -312,8 +381,9 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { } // expand and add @id mapping - const id = api.expandIri( - activeCtx, reverse, {vocab: true, base: false}, localCtx, defined); + const id = _expandIri( + activeCtx, reverse, {vocab: true, base: false}, localCtx, defined, + options); if(!_isAbsoluteIri(id)) { throw new JsonLdError( 'Invalid JSON-LD syntax; a @context @reverse value must be an ' + @@ -332,8 +402,8 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { } if(id !== term) { // expand and add @id mapping - id = api.expandIri( - activeCtx, id, {vocab: true, base: false}, localCtx, defined); + id = _expandIri( + activeCtx, id, {vocab: true, base: false}, localCtx, defined, options); if(!_isAbsoluteIri(id) && !api.isKeyword(id)) { throw new JsonLdError( 'Invalid JSON-LD syntax; a @context @id value must be an ' + @@ -355,7 +425,7 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { const prefix = term.substr(0, colon); if(prefix in localCtx) { // define parent prefix - api.createTermDefinition(activeCtx, localCtx, prefix, defined); + api.createTermDefinition(activeCtx, localCtx, prefix, defined, options); } if(activeCtx.mappings[prefix]) { @@ -379,6 +449,12 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { } } + // Handle term protection + if(value['@protected'] === true || + (defined['@protected'] === true && value['@protected'] !== false)) { + activeCtx.protected[term] = true; + } + // IRI mapping now defined defined[term] = true; @@ -393,8 +469,9 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { if(type !== '@id' && type !== '@vocab') { // expand @type to full IRI - type = api.expandIri( - activeCtx, type, {vocab: true, base: false}, localCtx, defined); + type = _expandIri( + activeCtx, type, {vocab: true, base: false}, localCtx, defined, + options); if(!_isAbsoluteIri(type)) { throw new JsonLdError( 'Invalid JSON-LD syntax; an @context @type value must be an ' + @@ -545,6 +622,25 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { } }; +/** + * Expands a string to a full IRI. The string may be a term, a prefix, a + * relative IRI, or an absolute IRI. The associated absolute IRI will be + * returned. + * + * @param activeCtx the current active context. + * @param value the string to expand. + * @param relativeTo options for how to resolve relative IRIs: + * base: true to resolve against the base IRI, false not to. + * vocab: true to concatenate after @vocab, false not to. + * @param {Object} [options] - processing options. + * + * @return the expanded value. + */ +api.expandIri = (activeCtx, value, relativeTo, options) => { + return _expandIri(activeCtx, value, relativeTo, undefined, undefined, + options); +}; + /** * Expands a string to a full IRI. The string may be a term, a prefix, a * relative IRI, or an absolute IRI. The associated absolute IRI will be @@ -559,10 +655,11 @@ api.createTermDefinition = (activeCtx, localCtx, term, defined) => { * during context processing). * @param defined a map for tracking cycles in context definitions (only given * if called during context processing). + * @param {Object} [options] - processing options. * * @return the expanded value. */ -api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => { +function _expandIri(activeCtx, value, relativeTo, localCtx, defined, options) { // already expanded if(value === null || !_isString(value) || api.isKeyword(value)) { return value; @@ -570,7 +667,7 @@ api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => { // define term dependency if not defined if(localCtx && value in localCtx && defined[value] !== true) { - api.createTermDefinition(activeCtx, localCtx, value, defined); + api.createTermDefinition(activeCtx, localCtx, value, defined, options); } relativeTo = relativeTo || {}; @@ -602,7 +699,7 @@ api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => { // prefix dependency not defined, define it if(localCtx && prefix in localCtx) { - api.createTermDefinition(activeCtx, localCtx, prefix, defined); + api.createTermDefinition(activeCtx, localCtx, prefix, defined, options); } // use mapping if prefix is defined @@ -626,7 +723,7 @@ api.expandIri = (activeCtx, value, relativeTo, localCtx, defined) => { } return value; -}; +} /** * Gets the initial context. @@ -650,7 +747,8 @@ api.getInitialContext = options => { mappings: {}, inverse: null, getInverse: _createInverseContext, - clone: _cloneActiveContext + clone: _cloneActiveContext, + protected: {} }; // TODO: consider using LRU cache instead if(INITIAL_CONTEXT_CACHE.size === INITIAL_CONTEXT_CACHE_MAX_SIZE) { @@ -826,6 +924,7 @@ api.getInitialContext = options => { child.clone = this.clone; child.inverse = null; child.getInverse = this.getInverse; + child.protected = util.clone(this.protected); if('@language' in this) { child['@language'] = this['@language']; } @@ -838,18 +937,21 @@ api.getInitialContext = options => { /** * Gets the value for the given active context key and type, null if none is - * set. + * set or undefined if none is set and type is '@context'. * * @param ctx the active context. * @param key the context key. * @param [type] the type of value to get (eg: '@id', '@type'), if not * specified gets the entire entry for a key, null if not found. * - * @return the value. + * @return the value, null, or undefined. */ api.getContextValue = (ctx, key, type) => { - // return null for invalid key + // invalid key if(key === null) { + if(type === '@context') { + return undefined; + } return null; } @@ -872,6 +974,9 @@ api.getContextValue = (ctx, key, type) => { return ctx[type]; } + if(type === '@context') { + return undefined; + } return null; }; @@ -935,6 +1040,7 @@ api.isKeyword = v => { case '@omitDefault': case '@prefix': case '@preserve': + case '@protected': case '@requireAll': case '@reverse': case '@set': diff --git a/lib/expand.js b/lib/expand.js index a7a2ba10..1314cbf9 100644 --- a/lib/expand.js +++ b/lib/expand.js @@ -9,7 +9,8 @@ const { isArray: _isArray, isObject: _isObject, isEmptyObject: _isEmptyObject, - isString: _isString + isString: _isString, + isUndefined: _isUndefined } = require('./types'); const { @@ -77,7 +78,8 @@ api.expand = ({ if(!_isArray(element) && !_isObject(element)) { // drop free-floating scalars that are not in lists unless custom mapped if(!insideList && (activeProperty === null || - _expandIri(activeCtx, activeProperty, {vocab: true}) === '@graph')) { + _expandIri(activeCtx, activeProperty, {vocab: true}, + options) === '@graph')) { // TODO: use `await` to support async const mapped = expansionMap({ unmappedValue: element, @@ -93,7 +95,7 @@ api.expand = ({ } // expand element according to value expansion rules - return _expandValue({activeCtx, activeProperty, value: element}); + return _expandValue({activeCtx, activeProperty, value: element, options}); } // recursively expand array @@ -155,7 +157,7 @@ api.expand = ({ // look for scoped context on @type let keys = Object.keys(element).sort(); for(const key of keys) { - const expandedProperty = _expandIri(activeCtx, key, {vocab: true}); + const expandedProperty = _expandIri(activeCtx, key, {vocab: true}, options); if(expandedProperty === '@type') { // set scopped contexts from @type // avoid sorting if possible @@ -165,7 +167,7 @@ api.expand = ({ (value.length > 1 ? value.slice().sort() : value) : [value]; for(const type of types) { const ctx = _getContextValue(activeCtx, type, '@context'); - if(ctx) { + if(!_isUndefined(ctx)) { activeCtx = _processContext({activeCtx, localCtx: ctx, options}); } } @@ -174,7 +176,7 @@ api.expand = ({ // expand the active property const expandedActiveProperty = _expandIri( - activeCtx, activeProperty, {vocab: true}); + activeCtx, activeProperty, {vocab: true}, options); // process each key and value in element, ignoring @nest content let rval = {}; @@ -352,7 +354,7 @@ function _expandObject({ } // expand property - let expandedProperty = _expandIri(activeCtx, key, {vocab: true}); + let expandedProperty = _expandIri(activeCtx, key, {vocab: true}, options); // drop non-absolute IRI keys that aren't keywords unless custom mapped if(expandedProperty === null || @@ -422,7 +424,7 @@ function _expandObject({ _addValue( expandedParent, '@id', _asArray(value).map(v => - _isString(v) ? _expandIri(activeCtx, v, {base: true}) : v), + _isString(v) ? _expandIri(activeCtx, v, {base: true}, options) : v), {propertyIsArray: options.isFrame}); continue; } @@ -433,7 +435,7 @@ function _expandObject({ expandedParent, '@type', _asArray(value).map(v => _isString(v) ? - _expandIri(activeCtx, v, {base: true, vocab: true}) : v), + _expandIri(activeCtx, v, {base: true, vocab: true}, options) : v), {propertyIsArray: options.isFrame}); continue; } @@ -555,15 +557,20 @@ function _expandObject({ // use potential scoped context for key let termCtx = activeCtx; const ctx = _getContextValue(activeCtx, key, '@context'); - if(ctx) { - termCtx = _processContext({activeCtx, localCtx: ctx, options}); + if(!_isUndefined(ctx)) { + // Note: spec's `from term` var is named `isPropertyTermScopedContext` + termCtx = _processContext({ + activeCtx, + localCtx: ctx, + options: {...options, isPropertyTermScopedContext: true} + }); } const container = _getContextValue(termCtx, key, '@container') || []; if(container.includes('@language') && _isObject(value)) { // handle language map container (skip if value is not an object) - expandedValue = _expandLanguageMap(termCtx, value); + expandedValue = _expandLanguageMap(termCtx, value, options); } else if(container.includes('@index') && _isObject(value)) { // handle index container (skip if value is not an object) const asGraph = container.includes('@graph'); @@ -703,7 +710,7 @@ function _expandObject({ const nestedValues = _isArray(element[key]) ? element[key] : [element[key]]; for(const nv of nestedValues) { if(!_isObject(nv) || Object.keys(nv).some(k => - _expandIri(activeCtx, k, {vocab: true}) === '@value')) { + _expandIri(activeCtx, k, {vocab: true}, options) === '@value')) { throw new JsonLdError( 'Invalid JSON-LD syntax; nested value must be a node object.', 'jsonld.SyntaxError', @@ -729,21 +736,23 @@ function _expandObject({ * @param activeCtx the active context to use. * @param activeProperty the active property the value is associated with. * @param value the value to expand. + * @param {Object} [options] - processing options. * * @return the expanded value. */ -function _expandValue({activeCtx, activeProperty, value}) { +function _expandValue({activeCtx, activeProperty, value, options}) { // nothing to expand if(value === null || value === undefined) { return null; } // special-case expand @id and @type (skips '@id' expansion) - const expandedProperty = _expandIri(activeCtx, activeProperty, {vocab: true}); + const expandedProperty = _expandIri( + activeCtx, activeProperty, {vocab: true}, options); if(expandedProperty === '@id') { - return _expandIri(activeCtx, value, {base: true}); + return _expandIri(activeCtx, value, {base: true}, options); } else if(expandedProperty === '@type') { - return _expandIri(activeCtx, value, {vocab: true, base: true}); + return _expandIri(activeCtx, value, {vocab: true, base: true}, options); } // get type definition from context @@ -751,11 +760,13 @@ function _expandValue({activeCtx, activeProperty, value}) { // do @id expansion (automatic for @graph) if((type === '@id' || expandedProperty === '@graph') && _isString(value)) { - return {'@id': _expandIri(activeCtx, value, {base: true})}; + return {'@id': _expandIri(activeCtx, value, {base: true}, options)}; } // do @id expansion w/vocab if(type === '@vocab' && _isString(value)) { - return {'@id': _expandIri(activeCtx, value, {vocab: true, base: true})}; + return { + '@id': _expandIri(activeCtx, value, {vocab: true, base: true}, options) + }; } // do not expand keyword values @@ -789,14 +800,15 @@ function _expandValue({activeCtx, activeProperty, value}) { * * @param activeCtx the active context to use. * @param languageMap the language map to expand. + * @param {Object} [options] - processing options. * * @return the expanded language map. */ -function _expandLanguageMap(activeCtx, languageMap) { +function _expandLanguageMap(activeCtx, languageMap, options) { const rval = []; const keys = Object.keys(languageMap).sort(); for(const key of keys) { - const expandedKey = _expandIri(activeCtx, key, {vocab: true}); + const expandedKey = _expandIri(activeCtx, key, {vocab: true}, options); let val = languageMap[key]; if(!_isArray(val)) { val = [val]; @@ -830,7 +842,7 @@ function _expandIndexMap( for(let key of keys) { // if indexKey is @type, there may be a context defined for it const ctx = _getContextValue(activeCtx, key, '@context'); - if(ctx) { + if(!_isUndefined(ctx)) { activeCtx = _processContext({activeCtx, localCtx: ctx, options}); } @@ -840,10 +852,10 @@ function _expandIndexMap( } // expand for @type, but also for @none - const expandedKey = _expandIri(activeCtx, key, {vocab: true}); + const expandedKey = _expandIri(activeCtx, key, {vocab: true}, options); if(indexKey === '@id') { // expand document relative - key = _expandIri(activeCtx, key, {base: true}); + key = _expandIri(activeCtx, key, {base: true}, options); } else if(indexKey === '@type') { key = expandedKey; } diff --git a/lib/jsonld.js b/lib/jsonld.js index 5d5d209c..1d298371 100644 --- a/lib/jsonld.js +++ b/lib/jsonld.js @@ -62,8 +62,7 @@ const { const { getInitialContext: _getInitialContext, process: _processContext, - getAllContexts: _getAllContexts, - expandIri: _expandIri + getAllContexts: _getAllContexts } = require('./context'); const { diff --git a/tests/test-common.js b/tests/test-common.js index 256fa844..b826974b 100644 --- a/tests/test-common.js +++ b/tests/test-common.js @@ -61,6 +61,23 @@ const TEST_TYPES = { /compact-manifest.jsonld#ttn01$/, /compact-manifest.jsonld#ttn02$/, /compact-manifest.jsonld#ttn03$/, + // property-valued indexes + /compact-manifest.jsonld#tpi01$/, + /compact-manifest.jsonld#tpi02$/, + /compact-manifest.jsonld#tpi03$/, + /compact-manifest.jsonld#tpi04$/, + /compact-manifest.jsonld#tpi05$/, + /compact-manifest.jsonld#tpi06$/, + // JSON literals + /compact-manifest.jsonld#tjs01$/, + /compact-manifest.jsonld#tjs02$/, + /compact-manifest.jsonld#tjs03$/, + /compact-manifest.jsonld#tjs04$/, + /compact-manifest.jsonld#tjs05$/, + /compact-manifest.jsonld#tjs06$/, + /compact-manifest.jsonld#tjs07$/, + /compact-manifest.jsonld#tjs08$/, + /compact-manifest.jsonld#tjs09$/, ] }, fn: 'compact', @@ -118,17 +135,32 @@ const TEST_TYPES = { /expand-manifest.jsonld#th020$/, /expand-manifest.jsonld#th021$/, /expand-manifest.jsonld#th022$/, - // sealed - /expand-manifest.jsonld#tse01$/, - /expand-manifest.jsonld#tse02$/, - /expand-manifest.jsonld#tse03$/, - /expand-manifest.jsonld#tse04$/, - /expand-manifest.jsonld#tse05$/, - /expand-manifest.jsonld#tse06$/, - /expand-manifest.jsonld#tse08$/, - /expand-manifest.jsonld#tse09$/, // @type: @none /expand-manifest.jsonld#ttn02$/, + // property index maps + /expand-manifest.jsonld#tpi01$/, + /expand-manifest.jsonld#tpi02$/, + /expand-manifest.jsonld#tpi03$/, + /expand-manifest.jsonld#tpi04$/, + /expand-manifest.jsonld#tpi05$/, + /expand-manifest.jsonld#tpi06$/, + /expand-manifest.jsonld#tpi07$/, + /expand-manifest.jsonld#tpi08$/, + /expand-manifest.jsonld#tpi09$/, + /expand-manifest.jsonld#tpi10$/, + /expand-manifest.jsonld#tpi11$/, + // JSON literals + /expand-manifest.jsonld#tjs01$/, + /expand-manifest.jsonld#tjs02$/, + /expand-manifest.jsonld#tjs03$/, + /expand-manifest.jsonld#tjs04$/, + /expand-manifest.jsonld#tjs05$/, + /expand-manifest.jsonld#tjs06$/, + /expand-manifest.jsonld#tjs07$/, + /expand-manifest.jsonld#tjs08$/, + /expand-manifest.jsonld#tjs09$/, + /expand-manifest.jsonld#tjs10$/, + /expand-manifest.jsonld#tjs11$/, // remote /remote-doc-manifest.jsonld#t0005$/, /remote-doc-manifest.jsonld#t0006$/, @@ -214,6 +246,14 @@ const TEST_TYPES = { /fromRdf-manifest.jsonld#tli01$/, /fromRdf-manifest.jsonld#tli02$/, /fromRdf-manifest.jsonld#tli03$/, + // JSON literals + /fromRdf-manifest.jsonld#tjs01$/, + /fromRdf-manifest.jsonld#tjs02$/, + /fromRdf-manifest.jsonld#tjs03$/, + /fromRdf-manifest.jsonld#tjs04$/, + /fromRdf-manifest.jsonld#tjs05$/, + /fromRdf-manifest.jsonld#tjs06$/, + /fromRdf-manifest.jsonld#tjs07$/, ] }, fn: 'fromRDF', @@ -252,6 +292,22 @@ const TEST_TYPES = { /toRdf-manifest.jsonld#th001$/, /toRdf-manifest.jsonld#th002$/, /toRdf-manifest.jsonld#th003$/, + // JSON literal + /toRdf-manifest.jsonld#tjs01$/, + /toRdf-manifest.jsonld#tjs02$/, + /toRdf-manifest.jsonld#tjs03$/, + /toRdf-manifest.jsonld#tjs04$/, + /toRdf-manifest.jsonld#tjs05$/, + /toRdf-manifest.jsonld#tjs06$/, + /toRdf-manifest.jsonld#tjs07$/, + /toRdf-manifest.jsonld#tjs08$/, + /toRdf-manifest.jsonld#tjs09$/, + /toRdf-manifest.jsonld#tjs10$/, + /toRdf-manifest.jsonld#tjs11$/, + /toRdf-manifest.jsonld#tjs12$/, + /toRdf-manifest.jsonld#tjs13$/, + // number fixes + /toRdf-manifest.jsonld#trt01$/, ] }, fn: 'toRDF',