Skip to content

Commit 06cc9a1

Browse files
gkelloggdavidlehn
authored andcommitted
Support default values for @type when framing.
1 parent e1e4a4e commit 06cc9a1

File tree

6 files changed

+64
-42
lines changed

6 files changed

+64
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
'i18n-datatype'.
4040
- Top level `@graph` omitted if `omitGraph` is `true`.
4141
- Check for invalid values of `@embed`.
42+
- Support default values for `@type` when framing.
4243

4344
## 2.0.2 - 2020-01-17
4445

lib/expand.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,20 @@ async function _expandObject({
515515
}
516516

517517
if(expandedProperty === '@type') {
518-
_validateTypeValue(value);
518+
// if framing, can be a default object, but need to expand
519+
// key to determine that
520+
if(_isObject(value)) {
521+
const expandedValue = {};
522+
for(const [k, v] of Object.entries(value)) {
523+
const kk = _expandIri(typeScopedContext, k, {vocab: true});
524+
const vv = _asArray(v).map(vvv =>
525+
_expandIri(typeScopedContext, vvv, {base: true, vocab: true})
526+
);
527+
expandedValue[kk] = vv;
528+
}
529+
value = expandedValue;
530+
}
531+
_validateTypeValue(value, options.isFrame);
519532
_addValue(
520533
expandedParent, '@type',
521534
_asArray(value).map(v =>

lib/frame.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,14 @@ api.frame = (state, subjects, frame, parent, property = null) => {
270270
// handle defaults
271271
for(const prop of Object.keys(frame).sort()) {
272272
// skip keywords
273-
if(isKeyword(prop)) {
273+
if(prop === '@type') {
274+
if(!types.isObject(frame[prop][0]) ||
275+
!frame[prop][0].hasOwnProperty('@default'))
276+
{
277+
continue;
278+
}
279+
// allow through default types
280+
} else if(isKeyword(prop)) {
274281
continue;
275282
}
276283

@@ -526,18 +533,24 @@ function _filterSubject(state, subject, frame, flags) {
526533
matchThis = true;
527534
} else if(frame['@type'].length === 1 &&
528535
types.isEmptyObject(frame['@type'][0])) {
529-
// match on wildcard @type
536+
// match on wildcard @type if there is a type
530537
matchThis = nodeValues.length > 0;
531538
} else {
532539
// match on a specific @type
533540
for(const type of frame['@type']) {
534-
if(nodeValues.some(tt => tt === type)) {
535-
return true;
541+
if(types.isObject(type) && '@default' in type) {
542+
// match on default object
543+
matchThis = true;
544+
} else {
545+
matchThis = matchThis || nodeValues.some(tt => tt === type);
536546
}
537547
}
538-
return false;
548+
}
549+
if(!flags.requireAll) {
550+
return matchThis;
539551
}
540552
}
553+
continue;
541554
}
542555

543556
// Forc a copy of this frame entry so it can be manipulated

lib/jsonld.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ const {fromRDF: _fromRDF} = require('./fromRdf');
4848
const {toRDF: _toRDF} = require('./toRdf');
4949

5050
const {
51-
frameMergedOrDefault: _frameMergedOrDefault
51+
frameMergedOrDefault: _frameMergedOrDefault,
52+
cleanupNull: _cleanupNull,
53+
cleanupPreserve: _cleanupPreserve
5254
} = require('./frame');
5355

5456
const {
@@ -70,8 +72,7 @@ const {
7072

7173
const {
7274
compact: _compact,
73-
compactIri: _compactIri,
74-
removePreserve: _removePreserve
75+
compactIri: _compactIri
7576
} = require('./compact');
7677

7778
const {
@@ -225,12 +226,6 @@ jsonld.compact = async function(input, ctx, options) {
225226
ctx = ctx[0];
226227
}
227228

228-
if(options.framing) {
229-
// remove @preserve from results
230-
options.link = {};
231-
compacted = _removePreserve(activeCtx, compacted, options);
232-
}
233-
234229
// add context and/or @graph
235230
if(_isArray(compacted)) {
236231
// use '@graph' keyword
@@ -493,13 +488,17 @@ jsonld.frame = async function(input, frame, options) {
493488
opts.is11 = _processingMode(activeCtx, 1.1);
494489

495490
// do framing
496-
const framed = _frameMergedOrDefault(expanded, expandedFrame, opts);
491+
let framed = _frameMergedOrDefault(expanded, expandedFrame, opts);
497492

498493
opts.graph = !options.omitGraph;
499494
opts.skipExpansion = true;
500495
opts.link = {};
501496
opts.framing = true;
502-
const compacted = await jsonld.compact(framed, frameContext, opts);
497+
let compacted = await jsonld.compact(framed, frameContext, opts);
498+
499+
// replace @null with null, compacting arrays
500+
opts.link = {};
501+
compacted = _cleanupNull(compacted, opts);
503502

504503
return compacted;
505504
};

lib/util.js

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -147,31 +147,33 @@ api.parseLinkHeader = header => {
147147
*
148148
* @param v the value to check.
149149
*/
150-
api.validateTypeValue = v => {
151-
// can be a string or an empty object
152-
if(types.isString(v) || types.isEmptyObject(v)) {
150+
api.validateTypeValue = (v, isFrame) => {
151+
if(types.isString(v)) {
153152
return;
154153
}
155154

156-
// must be an array
157-
let isValid = false;
158-
if(types.isArray(v)) {
159-
// must contain only strings
160-
isValid = true;
161-
for(let i = 0; i < v.length; ++i) {
162-
if(!(types.isString(v[i]))) {
163-
isValid = false;
164-
break;
165-
}
155+
if(types.isArray(v) && v.every(vv => types.isString(vv))) {
156+
return;
157+
} else if(isFrame && types.isObject(v)) {
158+
switch(Object.keys(v).length) {
159+
case 0:
160+
// empty object is wildcard
161+
return;
162+
case 1:
163+
// default entry is all strings
164+
if('@default' in v &&
165+
api.asArray(v['@default']).every(vv => types.isString(vv)))
166+
{
167+
return;
168+
}
166169
}
167170
}
168171

169-
if(!isValid) {
170-
throw new JsonLdError(
171-
'Invalid JSON-LD syntax; "@type" value must a string, an array of ' +
172-
'strings, or an empty object.', 'jsonld.SyntaxError',
173-
{code: 'invalid type value', value: v});
174-
}
172+
throw new JsonLdError(
173+
'Invalid JSON-LD syntax; "@type" value must a string, an array of ' +
174+
'strings, an empty object, ' +
175+
'or a default object.', 'jsonld.SyntaxError',
176+
{code: 'invalid type value', value: v});
175177
};
176178

177179
/**

tests/test-common.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,12 @@ const TEST_TYPES = {
126126
specVersion: ['json-ld-1.0'],
127127
// FIXME
128128
idRegex: [
129-
// default value for @type
130-
/frame-manifest.jsonld#t0064$/,
131-
// @container: @graph
132-
/frame-manifest.jsonld#tg010$/,
133129
// blank nodes
134130
/frame-manifest.jsonld#t0052$/,
135131
/frame-manifest.jsonld#t0053$/,
136132
// lists
137133
/frame-manifest.jsonld#t0055$/,
138134
/frame-manifest.jsonld#t0058$/,
139-
// @preserve and @container: @set
140-
/frame-manifest.jsonld#t0062$/,
141135
// requireAll
142136
/frame-manifest.jsonld#tra01$/,
143137
/frame-manifest.jsonld#tra02$/,

0 commit comments

Comments
 (0)