Skip to content

Commit c119ce4

Browse files
committed
Make RDF 1.2 literals with base direction output as @direction
1 parent 586fc7b commit c119ce4

File tree

3 files changed

+58
-48
lines changed

3 files changed

+58
-48
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Optionally, the following parameters can be set in the `JsonLdSerializer` constr
174174
* `excludeContext`: If a `context` or `baseIRI` is set, the context will be emitted into the output stream, unless this option is set to `true`. _(Default: `false`)_
175175
* `useRdfType`: An optional boolean indicating if rdf:type predicates should be emitted directly, instead of @type. _(Default: `false`)_
176176
* `useNativeTypes`: An optional boolean indicating if literals should be converted to primitive types, such as booleans and integers. _(Default: `false`)_
177-
* `rdfDirection`: The [mode](https://w3c.github.io/json-ld-api/#dom-jsonldoptions-rdfdirection) under which `@direction` should be handled. If undefined, `@direction` is ignored. Alternatively, it can be set to either `'i18n-datatype'` or `'compound-literal'` _(Default: `undefined`)_
177+
* `rdfDirection`: The [mode](https://w3c.github.io/json-ld-api/#dom-jsonldoptions-rdfdirection) under which `@direction` should be handled. If undefined, `@direction` is considered a regular RDF 1.2 literal with a base direction. Alternatively, it can be set to either `'i18n-datatype'` or `'compound-literal'` _(Default: `undefined`)_
178178

179179
```javascript
180180
new JsonLdSerializer({

lib/Util.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export class Util {
6666
? Util.stringToNativeType(term.value, term.datatype.value) : term.value,
6767
};
6868
if (term.language) {
69+
if (term.direction && !options.rdfDirection) {
70+
return { ...rawValue, '@language': term.language, '@direction': term.direction };
71+
}
6972
return { ...rawValue, '@language': term.language };
7073
} else if (!stringType && typeof rawValue['@value'] === 'string') {
7174
return { ...rawValue, '@type': term.datatype.value };

test/lib/Util-test.ts

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import {blankNode, defaultGraph, literal, namedNode} from "@rdfjs/data-model";
1+
import { DataFactory } from "rdf-data-factory";
22
import {Util} from "../../lib/Util";
33
import {ERROR_CODES, ErrorCoded, JsonLdContextNormalized} from "jsonld-context-parser";
44

5+
const DF = new DataFactory();
6+
57
describe('Util', () => {
68

79
describe('stringToNativeType', () => {
@@ -91,168 +93,173 @@ describe('Util', () => {
9193

9294
describe('termToValue', () => {
9395
it('should handle named nodes', async () => {
94-
return expect(Util.termToValue(namedNode('http://ex.org/'), new JsonLdContextNormalized({})))
96+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), new JsonLdContextNormalized({})))
9597
.toEqual({ '@id': 'http://ex.org/' });
9698
});
9799

98100
it('should handle named nodes with compactIds true', async () => {
99-
return expect(Util.termToValue(namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { compactIds: true }))
101+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { compactIds: true }))
100102
.toEqual('http://ex.org/');
101103
});
102104

103105
it('should handle named nodes without context vocab in vocab mode', async () => {
104-
return expect(Util.termToValue(namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { vocab: true }))
106+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { vocab: true }))
105107
.toEqual({ '@id': 'http://ex.org/' });
106108
});
107109

108110
it('should handle named nodes without context vocab in base mode', async () => {
109-
return expect(Util.termToValue(namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { vocab: false }))
111+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), new JsonLdContextNormalized({}), { vocab: false }))
110112
.toEqual({ '@id': 'http://ex.org/' });
111113
});
112114

113115
it('should handle named nodes with context vocab in vocab mode', async () => {
114116
const context = new JsonLdContextNormalized({ '@vocab': 'http://ex.org/' });
115-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: true }))
117+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: true }))
116118
.toEqual({ '@id': '' });
117119
});
118120

119121
it('should handle named nodes with context vocab in base mode', async () => {
120122
const context = new JsonLdContextNormalized({ '@vocab': 'http://ex.org/' });
121-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: false }))
123+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: false }))
122124
.toEqual({ '@id': 'http://ex.org/' });
123125
});
124126

125127
it('should handle named nodes with context base in vocab mode', async () => {
126128
const context = new JsonLdContextNormalized({ '@base': 'http://ex.org/' });
127-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: true }))
129+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: true }))
128130
.toEqual({ '@id': 'http://ex.org/' });
129131
});
130132

131133
it('should handle named nodes with context base in base mode', async () => {
132134
const context = new JsonLdContextNormalized({ '@base': 'http://ex.org/' });
133-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: false }))
135+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: false }))
134136
.toEqual({ '@id': '' });
135137
});
136138

137139
it('should handle named nodes with context term in vocab mode', async () => {
138140
const context = new JsonLdContextNormalized({ ex: 'http://ex.org/' });
139-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: true }))
141+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: true }))
140142
.toEqual({ '@id': 'ex' });
141143
});
142144

143145
it('should handle named nodes with context term in base mode', async () => {
144146
const context = new JsonLdContextNormalized({ ex: 'http://ex.org/' });
145-
return expect(Util.termToValue(namedNode('http://ex.org/'), context, { vocab: false }))
147+
return expect(Util.termToValue(DF.namedNode('http://ex.org/'), context, { vocab: false }))
146148
.toEqual({ '@id': 'http://ex.org/' });
147149
});
148150

149151
it('should handle named nodes with context prefix in vocab mode', async () => {
150152
const context = new JsonLdContextNormalized({ ex: 'http://ex.org/' });
151-
return expect(Util.termToValue(namedNode('http://ex.org/aa'), context, { vocab: true }))
153+
return expect(Util.termToValue(DF.namedNode('http://ex.org/aa'), context, { vocab: true }))
152154
.toEqual({ '@id': 'ex:aa' });
153155
});
154156

155157
it('should handle named nodes with context prefix in base mode', async () => {
156158
const context = new JsonLdContextNormalized({ ex: 'http://ex.org/' });
157-
return expect(Util.termToValue(namedNode('http://ex.org/aa'), context, { vocab: false }))
159+
return expect(Util.termToValue(DF.namedNode('http://ex.org/aa'), context, { vocab: false }))
158160
.toEqual({ '@id': 'ex:aa' });
159161
});
160162

161163
it('should handle default graphs', async () => {
162-
return expect(Util.termToValue(defaultGraph(), new JsonLdContextNormalized({})))
164+
return expect(Util.termToValue(DF.defaultGraph(), new JsonLdContextNormalized({})))
163165
.toEqual({ '@id': '' });
164166
});
165167

166168
it('should handle default graphs with compactIds true', async () => {
167-
return expect(Util.termToValue(defaultGraph(), new JsonLdContextNormalized({}), { compactIds: true }))
169+
return expect(Util.termToValue(DF.defaultGraph(), new JsonLdContextNormalized({}), { compactIds: true }))
168170
.toEqual('');
169171
});
170172

171173
it('should handle blank nodes', async () => {
172-
return expect(Util.termToValue(blankNode('b0'), new JsonLdContextNormalized({})))
174+
return expect(Util.termToValue(DF.blankNode('b0'), new JsonLdContextNormalized({})))
173175
.toEqual({ '@id': '_:b0' });
174176
});
175177

176178
it('should handle blank nodes with compactIds true', async () => {
177-
return expect(Util.termToValue(blankNode('b0'), new JsonLdContextNormalized({}), { compactIds: true }))
179+
return expect(Util.termToValue(DF.blankNode('b0'), new JsonLdContextNormalized({}), { compactIds: true }))
178180
.toEqual('_:b0');
179181
});
180182

181-
it('should handle literals without language and datatype with useNativeTypes false', async () => {
182-
return expect(Util.termToValue(literal('abc'), new JsonLdContextNormalized({})))
183+
it('should handle DF.literals without language and datatype with useNativeTypes false', async () => {
184+
return expect(Util.termToValue(DF.literal('abc'), new JsonLdContextNormalized({})))
183185
.toEqual({ '@value': 'abc' });
184186
});
185187

186-
it('should handle literals without language and datatype with useNativeTypes true', async () => {
187-
return expect(Util.termToValue(literal('abc'), new JsonLdContextNormalized({}), { useNativeTypes: true }))
188+
it('should handle DF.literals without language and datatype with useNativeTypes true', async () => {
189+
return expect(Util.termToValue(DF.literal('abc'), new JsonLdContextNormalized({}), { useNativeTypes: true }))
188190
.toEqual({ '@value': 'abc' });
189191
});
190192

191-
it('should handle literals with language with useNativeTypes false', async () => {
192-
return expect(Util.termToValue(literal('abc', 'en'), new JsonLdContextNormalized({})))
193+
it('should handle DF.literals with language with useNativeTypes false', async () => {
194+
return expect(Util.termToValue(DF.literal('abc', 'en'), new JsonLdContextNormalized({})))
193195
.toEqual({ '@value': 'abc', '@language': 'en' });
194196
});
195197

196-
it('should handle literals with language with useNativeTypes true', async () => {
197-
return expect(Util.termToValue(literal('abc', 'en'), new JsonLdContextNormalized({}), { useNativeTypes: true }))
198+
it('should handle DF.literals with language with useNativeTypes true', async () => {
199+
return expect(Util.termToValue(DF.literal('abc', 'en'), new JsonLdContextNormalized({}), { useNativeTypes: true }))
198200
.toEqual({ '@value': 'abc', '@language': 'en' });
199201
});
200202

201-
it('should handle string literals with unknown datatype with useNativeTypes false', async () => {
202-
return expect(Util.termToValue(literal('abc', namedNode('http://ex.org/type')), new JsonLdContextNormalized({})))
203+
it('should handle string DF.literals with unknown datatype with useNativeTypes false', async () => {
204+
return expect(Util.termToValue(DF.literal('abc', DF.namedNode('http://ex.org/type')), new JsonLdContextNormalized({})))
203205
.toEqual({ '@value': 'abc', '@type': 'http://ex.org/type' });
204206
});
205207

206-
it('should handle string literals with unknown datatype with useNativeTypes true', async () => {
207-
return expect(Util.termToValue(literal('abc', namedNode('http://ex.org/type')), new JsonLdContextNormalized({}), { useNativeTypes: true }))
208+
it('should handle string DF.literals with unknown datatype with useNativeTypes true', async () => {
209+
return expect(Util.termToValue(DF.literal('abc', DF.namedNode('http://ex.org/type')), new JsonLdContextNormalized({}), { useNativeTypes: true }))
208210
.toEqual({ '@value': 'abc', '@type': 'http://ex.org/type' });
209211
});
210212

211-
it('should handle string literals with number datatype with useNativeTypes false', async () => {
212-
return expect(Util.termToValue(literal('10', namedNode('http://www.w3.org/2001/XMLSchema#number')), new JsonLdContextNormalized({})))
213+
it('should handle string DF.literals with number datatype with useNativeTypes false', async () => {
214+
return expect(Util.termToValue(DF.literal('10', DF.namedNode('http://www.w3.org/2001/XMLSchema#number')), new JsonLdContextNormalized({})))
213215
.toEqual({ '@value': '10', '@type': 'http://www.w3.org/2001/XMLSchema#number' });
214216
});
215217

216-
it('should handle string literals with number datatype with useNativeTypes true', async () => {
217-
return expect(Util.termToValue(literal('10', namedNode('http://www.w3.org/2001/XMLSchema#number')), new JsonLdContextNormalized({}),
218+
it('should handle string DF.literals with number datatype with useNativeTypes true', async () => {
219+
return expect(Util.termToValue(DF.literal('10', DF.namedNode('http://www.w3.org/2001/XMLSchema#number')), new JsonLdContextNormalized({}),
218220
{ useNativeTypes: true })).toEqual({ '@value': 10 });
219221
});
220222

221-
it('should handle string literals with decimal datatype with useNativeTypes true', async () => {
222-
return expect(Util.termToValue(literal('10', namedNode('http://www.w3.org/2001/XMLSchema#decimal')), new JsonLdContextNormalized({}),
223+
it('should handle string DF.literals with decimal datatype with useNativeTypes true', async () => {
224+
return expect(Util.termToValue(DF.literal('10', DF.namedNode('http://www.w3.org/2001/XMLSchema#decimal')), new JsonLdContextNormalized({}),
223225
{ useNativeTypes: true })).toEqual(
224226
{ '@value': '10', '@type': 'http://www.w3.org/2001/XMLSchema#decimal' });
225227
});
226228

227-
it('should handle string literals with JSON datatype', async () => {
228-
return expect(Util.termToValue(literal('true', namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
229+
it('should handle string DF.literals with JSON datatype', async () => {
230+
return expect(Util.termToValue(DF.literal('true', DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
229231
.toEqual({ '@value': true, '@type': '@json' });
230-
return expect(Util.termToValue(literal('{"a":"b"}', namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
232+
return expect(Util.termToValue(DF.literal('{"a":"b"}', DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
231233
.toEqual({ '@value': { a: 'b' }, '@type': '@json' });
232234
});
233235

234-
it('should handle string literals with I18N datatype', async () => {
235-
return expect(Util.termToValue(literal('bla', namedNode('https://www.w3.org/ns/i18n#en-us_rtl')), new JsonLdContextNormalized({}))).toEqual(
236+
it('should handle string DF.literals with I18N datatype', async () => {
237+
return expect(Util.termToValue(DF.literal('bla', DF.namedNode('https://www.w3.org/ns/i18n#en-us_rtl')), new JsonLdContextNormalized({}))).toEqual(
236238
{ '@value': 'bla', '@type': 'https://www.w3.org/ns/i18n#en-us_rtl' });
237239
});
238240

239-
it('should handle string literals with I18N datatype with rdfDirection: i18n-datatype', async () => {
240-
expect(Util.termToValue(literal('bla', namedNode('https://www.w3.org/ns/i18n#en-us_rtl')), new JsonLdContextNormalized({}),
241+
it('should handle string DF.literals with I18N datatype with rdfDirection: i18n-datatype', async () => {
242+
expect(Util.termToValue(DF.literal('bla', DF.namedNode('https://www.w3.org/ns/i18n#en-us_rtl')), new JsonLdContextNormalized({}),
241243
{ rdfDirection: 'i18n-datatype' })).toEqual(
242244
{ '@value': 'bla', '@language': 'en-us', '@direction': 'rtl' });
243-
expect(Util.termToValue(literal('bla', namedNode('https://www.w3.org/ns/i18n#_rtl')), new JsonLdContextNormalized({}),
245+
expect(Util.termToValue(DF.literal('bla', DF.namedNode('https://www.w3.org/ns/i18n#_rtl')), new JsonLdContextNormalized({}),
244246
{ rdfDirection: 'i18n-datatype' })).toEqual(
245247
{ '@value': 'bla', '@direction': 'rtl' });
246-
expect(Util.termToValue(literal('bla', namedNode('https://www.w3.org/ns/i18n#en-us_')), new JsonLdContextNormalized({}),
248+
expect(Util.termToValue(DF.literal('bla', DF.namedNode('https://www.w3.org/ns/i18n#en-us_')), new JsonLdContextNormalized({}),
247249
{ rdfDirection: 'i18n-datatype' })).toEqual(
248250
{ '@value': 'bla', '@language': 'en-us' });
249251
});
250252

251-
it('should throw on invalid string literals with JSON datatype', async () => {
252-
expect(() => Util.termToValue(literal('{', namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
253+
it('should handle string DF.literals with base direction with rdfDirection: undefined', async () => {
254+
expect(Util.termToValue(DF.literal('bla', { language: 'en-us', direction: 'rtl' }), new JsonLdContextNormalized({}))).toEqual(
255+
{ '@value': 'bla', '@language': 'en-us', '@direction': 'rtl' });
256+
});
257+
258+
it('should throw on invalid string DF.literals with JSON datatype', async () => {
259+
expect(() => Util.termToValue(DF.literal('{', DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({})))
253260
.toThrow('Invalid JSON literal');
254261
try {
255-
Util.termToValue(literal('{', namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({}));
262+
Util.termToValue(DF.literal('{', DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON')), new JsonLdContextNormalized({}));
256263
} catch(e) {
257264
expect(e).toBeInstanceOf(ErrorCoded);
258265
expect(e.code).toEqual(ERROR_CODES.INVALID_JSON_LITERAL);

0 commit comments

Comments
 (0)