n3 2.2.15 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/IRIs.js CHANGED
@@ -11,6 +11,7 @@ var _default = exports.default = {
11
11
  xsd: {
12
12
  decimal: `${XSD}decimal`,
13
13
  boolean: `${XSD}boolean`,
14
+ dateTime: `${XSD}dateTime`,
14
15
  double: `${XSD}double`,
15
16
  integer: `${XSD}integer`,
16
17
  string: `${XSD}string`
@@ -412,7 +412,7 @@ function literal(value, languageOrDataType) {
412
412
  return new Literal(`"${value}"@${languageOrDataType.language.toLowerCase()}${languageOrDataType.direction ? `--${languageOrDataType.direction.toLowerCase()}` : ''}`);
413
413
  }
414
414
 
415
- // Automatically determine datatype for booleans and numbers
415
+ // Automatically determine datatype for booleans, numbers, and dates
416
416
  let datatype = languageOrDataType ? languageOrDataType.value : '';
417
417
  if (datatype === '') {
418
418
  // Convert a boolean
@@ -424,6 +424,11 @@ function literal(value, languageOrDataType) {
424
424
  if (!Number.isNaN(value)) value = value > 0 ? 'INF' : '-INF';
425
425
  }
426
426
  }
427
+ // Convert a valid date
428
+ else if (value instanceof Date && !Number.isNaN(value.getTime())) {
429
+ datatype = xsd.dateTime;
430
+ value = value.toISOString();
431
+ }
427
432
  }
428
433
 
429
434
  // Create a datatyped literal
package/lib/N3Parser.js CHANGED
@@ -223,6 +223,19 @@ class N3Parser {
223
223
  return value;
224
224
  }
225
225
 
226
+ // ### `_readList` starts reading a list in the subject, predicate, or object position
227
+ _readList(token, subject, predicate, object) {
228
+ const stack = this._contextStack,
229
+ parent = stack.length && stack[stack.length - 1];
230
+ if (parent.type === '<<') {
231
+ return this._error('Unexpected list in reified triple', token);
232
+ }
233
+ // Start a new list
234
+ this._saveContext('list', this._graph, subject, predicate, object);
235
+ this._subject = null;
236
+ return this._readListItem;
237
+ }
238
+
226
239
  // ### `_readSubject` reads a quad's subject
227
240
  _readSubject(token) {
228
241
  this._predicate = null;
@@ -234,15 +247,7 @@ class N3Parser {
234
247
  this._saveContext('blank', this._graph, this._subject = this._factory.blankNode(), null, null);
235
248
  return this._readBlankNodeHead;
236
249
  case '(':
237
- const stack = this._contextStack,
238
- parent = stack.length && stack[stack.length - 1];
239
- if (parent.type === '<<') {
240
- return this._error('Unexpected list in reified triple', token);
241
- }
242
- // Start a new list
243
- this._saveContext('list', this._graph, this.RDF_NIL, null, null);
244
- this._subject = null;
245
- return this._readListItem;
250
+ return this._readList(token, this.RDF_NIL, null, null);
246
251
  case '{':
247
252
  // Start a new formula
248
253
  if (!this._n3Mode) return this._error('Unexpected graph', token);
@@ -322,6 +327,9 @@ class N3Parser {
322
327
  return this._completePredicateLiteral;
323
328
  } else this._predicate = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
324
329
  break;
330
+ case '(':
331
+ // In N3, a list can be a predicate
332
+ return this._n3Mode ? this._readList(token, this._subject, this.RDF_NIL, null) : this._error(`Expected entity but got ${type}`, token);
325
333
  case '[':
326
334
  if (this._n3Mode) {
327
335
  // Start a new quad with a new blank node as subject
@@ -359,15 +367,7 @@ class N3Parser {
359
367
  this._saveContext('blank', this._graph, this._subject, this._predicate, this._subject = this._factory.blankNode());
360
368
  return this._readBlankNodeHead;
361
369
  case '(':
362
- const stack = this._contextStack,
363
- parent = stack.length && stack[stack.length - 1];
364
- if (parent.type === '<<') {
365
- return this._error('Unexpected list in reified triple', token);
366
- }
367
- // Start a new list
368
- this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
369
- this._subject = null;
370
- return this._readListItem;
370
+ return this._readList(token, this._subject, this._predicate, this.RDF_NIL);
371
371
  case '{':
372
372
  // Start a new formula
373
373
  if (!this._n3Mode) return this._error('Unexpected graph', token);
@@ -501,6 +501,13 @@ class N3Parser {
501
501
  // No list tail if this was an empty list
502
502
  if (this._subject === this.RDF_NIL) return next;
503
503
  }
504
+ // Was this list the parent's predicate?
505
+ else if (this._object === null) {
506
+ // The next token is the object
507
+ next = this._readObject;
508
+ // No list tail if this was an empty list
509
+ if (this._predicate === this.RDF_NIL) return next;
510
+ }
504
511
  // The list was in the parent context's object
505
512
  else {
506
513
  next = this._getContextEndReader();
@@ -567,8 +574,12 @@ class N3Parser {
567
574
 
568
575
  // Is this the first element of the list?
569
576
  if (previousList === null) {
570
- // This list is either the subject or the object of its parent
571
- if (parent.predicate === null) parent.subject = list;else parent.object = list;
577
+ // The list is the subject of the parent
578
+ if (parent.predicate === null) parent.subject = list;
579
+ // The list is the predicate of the parent
580
+ else if (parent.object === null) parent.predicate = list;
581
+ // The list is the object of the parent
582
+ else parent.object = list;
572
583
  } else {
573
584
  // Continue the previous list with the current list
574
585
  this._emit(previousList, this.RDF_REST, list, this._graph);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.2.15",
3
+ "version": "2.3.0",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
package/src/IRIs.js CHANGED
@@ -6,6 +6,7 @@ export default {
6
6
  xsd: {
7
7
  decimal: `${XSD}decimal`,
8
8
  boolean: `${XSD}boolean`,
9
+ dateTime: `${XSD}dateTime`,
9
10
  double: `${XSD}double`,
10
11
  integer: `${XSD}integer`,
11
12
  string: `${XSD}string`,
@@ -424,7 +424,7 @@ function literal(value, languageOrDataType) {
424
424
  return new Literal(`"${value}"@${languageOrDataType.language.toLowerCase()}${languageOrDataType.direction ? `--${languageOrDataType.direction.toLowerCase()}` : ''}`);
425
425
  }
426
426
 
427
- // Automatically determine datatype for booleans and numbers
427
+ // Automatically determine datatype for booleans, numbers, and dates
428
428
  let datatype = languageOrDataType ? languageOrDataType.value : '';
429
429
  if (datatype === '') {
430
430
  // Convert a boolean
@@ -440,6 +440,11 @@ function literal(value, languageOrDataType) {
440
440
  value = value > 0 ? 'INF' : '-INF';
441
441
  }
442
442
  }
443
+ // Convert a valid date
444
+ else if (value instanceof Date && !Number.isNaN(value.getTime())) {
445
+ datatype = xsd.dateTime;
446
+ value = value.toISOString();
447
+ }
443
448
  }
444
449
 
445
450
  // Create a datatyped literal
package/src/N3Parser.js CHANGED
@@ -213,6 +213,18 @@ export default class N3Parser {
213
213
  return value;
214
214
  }
215
215
 
216
+ // ### `_readList` starts reading a list in the subject, predicate, or object position
217
+ _readList(token, subject, predicate, object) {
218
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
219
+ if (parent.type === '<<') {
220
+ return this._error('Unexpected list in reified triple', token);
221
+ }
222
+ // Start a new list
223
+ this._saveContext('list', this._graph, subject, predicate, object);
224
+ this._subject = null;
225
+ return this._readListItem;
226
+ }
227
+
216
228
  // ### `_readSubject` reads a quad's subject
217
229
  _readSubject(token) {
218
230
  this._predicate = null;
@@ -226,14 +238,7 @@ export default class N3Parser {
226
238
  this._subject = this._factory.blankNode(), null, null);
227
239
  return this._readBlankNodeHead;
228
240
  case '(':
229
- const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
230
- if (parent.type === '<<') {
231
- return this._error('Unexpected list in reified triple', token);
232
- }
233
- // Start a new list
234
- this._saveContext('list', this._graph, this.RDF_NIL, null, null);
235
- this._subject = null;
236
- return this._readListItem;
241
+ return this._readList(token, this.RDF_NIL, null, null);
237
242
  case '{':
238
243
  // Start a new formula
239
244
  if (!this._n3Mode)
@@ -330,6 +335,11 @@ export default class N3Parser {
330
335
  this._predicate = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
331
336
 
332
337
  break;
338
+ case '(':
339
+ // In N3, a list can be a predicate
340
+ return this._n3Mode ?
341
+ this._readList(token, this._subject, this.RDF_NIL, null) :
342
+ this._error(`Expected entity but got ${type}`, token);
333
343
  case '[':
334
344
  if (this._n3Mode) {
335
345
  // Start a new quad with a new blank node as subject
@@ -372,14 +382,7 @@ export default class N3Parser {
372
382
  this._subject = this._factory.blankNode());
373
383
  return this._readBlankNodeHead;
374
384
  case '(':
375
- const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
376
- if (parent.type === '<<') {
377
- return this._error('Unexpected list in reified triple', token);
378
- }
379
- // Start a new list
380
- this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
381
- this._subject = null;
382
- return this._readListItem;
385
+ return this._readList(token, this._subject, this._predicate, this.RDF_NIL);
383
386
  case '{':
384
387
  // Start a new formula
385
388
  if (!this._n3Mode)
@@ -523,6 +526,14 @@ export default class N3Parser {
523
526
  if (this._subject === this.RDF_NIL)
524
527
  return next;
525
528
  }
529
+ // Was this list the parent's predicate?
530
+ else if (this._object === null) {
531
+ // The next token is the object
532
+ next = this._readObject;
533
+ // No list tail if this was an empty list
534
+ if (this._predicate === this.RDF_NIL)
535
+ return next;
536
+ }
526
537
  // The list was in the parent context's object
527
538
  else {
528
539
  next = this._getContextEndReader();
@@ -600,9 +611,13 @@ export default class N3Parser {
600
611
 
601
612
  // Is this the first element of the list?
602
613
  if (previousList === null) {
603
- // This list is either the subject or the object of its parent
614
+ // The list is the subject of the parent
604
615
  if (parent.predicate === null)
605
616
  parent.subject = list;
617
+ // The list is the predicate of the parent
618
+ else if (parent.object === null)
619
+ parent.predicate = list;
620
+ // The list is the object of the parent
606
621
  else
607
622
  parent.object = list;
608
623
  }