n3 1.11.0 → 1.12.1

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/src/N3Lexer.js CHANGED
@@ -429,6 +429,11 @@ export default class N3Lexer {
429
429
  return err;
430
430
  }
431
431
 
432
+ // ### Strips off any starting UTF BOM mark.
433
+ _readStartingBom(input) {
434
+ return input.startsWith('\ufeff') ? input.substr(1) : input;
435
+ }
436
+
432
437
  // ## Public methods
433
438
 
434
439
  // ### `tokenize` starts the transformation of an N3 document into an array of tokens.
@@ -438,7 +443,7 @@ export default class N3Lexer {
438
443
 
439
444
  // If the input is a string, continuously emit tokens through the callback until the end
440
445
  if (typeof input === 'string') {
441
- this._input = input;
446
+ this._input = this._readStartingBom(input);
442
447
  // If a callback was passed, asynchronously call it
443
448
  if (typeof callback === 'function')
444
449
  queueMicrotask(() => this._tokenizeToEnd(callback, true));
@@ -453,7 +458,6 @@ export default class N3Lexer {
453
458
  }
454
459
  // Otherwise, the input must be a stream
455
460
  else {
456
- this._input = '';
457
461
  this._pendingBuffer = null;
458
462
  if (typeof input.setEncoding === 'function')
459
463
  input.setEncoding('utf8');
@@ -471,14 +475,18 @@ export default class N3Lexer {
471
475
  }
472
476
  // Otherwise, tokenize as far as possible
473
477
  else {
474
- this._input += data;
478
+ // Only read a BOM at the start
479
+ if (typeof this._input === 'undefined')
480
+ this._input = this._readStartingBom(typeof data === 'string' ? data : data.toString());
481
+ else
482
+ this._input += data;
475
483
  this._tokenizeToEnd(callback, false);
476
484
  }
477
485
  }
478
486
  });
479
487
  // Parses until the end
480
488
  input.on('end', () => {
481
- if (this._input !== null)
489
+ if (typeof this._input === 'string')
482
490
  this._tokenizeToEnd(callback, true);
483
491
  });
484
492
  input.on('error', callback);
package/src/N3Parser.js CHANGED
@@ -272,6 +272,13 @@ export default class N3Parser {
272
272
  // Additional semicolons can be safely ignored
273
273
  return this._predicate !== null ? this._readPredicate :
274
274
  this._error('Expected predicate but got ;', token);
275
+ case '[':
276
+ if (this._n3Mode) {
277
+ // Start a new quad with a new blank node as subject
278
+ this._saveContext('blank', this._graph, this._subject,
279
+ this._subject = this._blankNode(), null);
280
+ return this._readBlankNodeHead;
281
+ }
275
282
  case 'blank':
276
283
  if (!this._n3Mode)
277
284
  return this._error('Disallowed blank node as predicate', token);
@@ -368,13 +375,16 @@ export default class N3Parser {
368
375
  // Restore the parent context containing this blank node
369
376
  const empty = this._predicate === null;
370
377
  this._restoreContext();
378
+ // If the blank node was the object, restore previous context and read punctuation
379
+ if (this._object !== null)
380
+ return this._getContextEndReader();
381
+ // If the blank node was the predicate, continue reading the object
382
+ else if (this._predicate !== null)
383
+ return this._readObject;
371
384
  // If the blank node was the subject, continue reading the predicate
372
- if (this._object === null)
385
+ else
373
386
  // If the blank node was empty, it could be a named graph label
374
387
  return empty ? this._readPredicateOrNamedGraph : this._readPredicateAfterBlank;
375
- // If the blank node was the object, restore previous context and read punctuation
376
- else
377
- return this._getContextEndReader();
378
388
  }
379
389
 
380
390
  // ### `_readPredicateAfterBlank` reads a predicate after an anonymous blank node