n3 1.26.0 → 2.0.0-beta.2

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/N3Parser.js CHANGED
@@ -27,18 +27,17 @@ export default class N3Parser {
27
27
  this._readPredicateOrNamedGraph = this._readPredicate;
28
28
  // Support triples in other graphs
29
29
  this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
30
- // Whether the log:isImpliedBy predicate is supported
31
- this._isImpliedBy = options.isImpliedBy;
32
- // Support nesting of triples
33
- this._supportsRDFStar = format === '' || /star|\*$/.test(format);
34
30
  // Disable relative IRIs in N-Triples or N-Quads mode
35
31
  if (isLineMode)
36
32
  this._resolveRelativeIRI = iri => { return null; };
37
33
  this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' :
38
34
  options.blankNodePrefix.replace(/^(?!_:)/, '_:');
39
- this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3, isImpliedBy: this._isImpliedBy });
35
+ this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 });
40
36
  // Disable explicit quantifiers by default
41
37
  this._explicitQuantifiers = !!options.explicitQuantifiers;
38
+ // Disable parsing of unsupported versions by default
39
+ this._parseUnsupportedVersions = !!options.parseUnsupportedVersions;
40
+ this._version = options.version;
42
41
  }
43
42
 
44
43
  // ## Static class methods
@@ -116,6 +115,13 @@ export default class N3Parser {
116
115
  }
117
116
  }
118
117
 
118
+ // ### `_readBeforeTopContext` is called once only at the start of parsing.
119
+ _readBeforeTopContext(token) {
120
+ if (this._version && !this._isValidVersion(this._version))
121
+ return this._error(`Detected unsupported version as media type parameter: "${this._version}"`, token);
122
+ return this._readInTopContext(token);
123
+ }
124
+
119
125
  // ### `_readInTopContext` reads a token when in the top context
120
126
  _readInTopContext(token) {
121
127
  switch (token.type) {
@@ -135,6 +141,11 @@ export default class N3Parser {
135
141
  this._sparqlStyle = true;
136
142
  case '@base':
137
143
  return this._readBaseIRI;
144
+ // It could be a version declaration
145
+ case 'VERSION':
146
+ this._sparqlStyle = true;
147
+ case '@version':
148
+ return this._readVersion;
138
149
  // It could be a graph
139
150
  case '{':
140
151
  if (this._supportsNamedGraphs) {
@@ -199,6 +210,10 @@ export default class N3Parser {
199
210
  this._subject = this._factory.blankNode(), null, null);
200
211
  return this._readBlankNodeHead;
201
212
  case '(':
213
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
214
+ if (parent.type === '<<') {
215
+ return this._error('Unexpected list in reified triple', token);
216
+ }
202
217
  // Start a new list
203
218
  this._saveContext('list', this._graph, this.RDF_NIL, null, null);
204
219
  this._subject = null;
@@ -239,9 +254,13 @@ export default class N3Parser {
239
254
  this._subject = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
240
255
 
241
256
  break;
257
+ case '<<(':
258
+ if (!this._n3Mode)
259
+ return this._error('Disallowed triple term as subject', token);
260
+ this._saveContext('<<(', this._graph, null, null, null);
261
+ this._graph = null;
262
+ return this._readSubject;
242
263
  case '<<':
243
- if (!this._supportsRDFStar)
244
- return this._error('Unexpected RDF-star syntax', token);
245
264
  this._saveContext('<<', this._graph, null, null, null);
246
265
  this._graph = null;
247
266
  return this._readSubject;
@@ -271,6 +290,7 @@ export default class N3Parser {
271
290
  case '.':
272
291
  case ']':
273
292
  case '}':
293
+ case '|}':
274
294
  // Expected predicate didn't come, must have been trailing semicolon
275
295
  if (this._predicate === null)
276
296
  return this._error(`Unexpected ${type}`, token);
@@ -317,6 +337,10 @@ export default class N3Parser {
317
337
  this._subject = this._factory.blankNode());
318
338
  return this._readBlankNodeHead;
319
339
  case '(':
340
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
341
+ if (parent.type === '<<') {
342
+ return this._error('Unexpected list in reified triple', token);
343
+ }
320
344
  // Start a new list
321
345
  this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
322
346
  this._subject = null;
@@ -328,9 +352,11 @@ export default class N3Parser {
328
352
  this._saveContext('formula', this._graph, this._subject, this._predicate,
329
353
  this._graph = this._factory.blankNode());
330
354
  return this._readSubject;
355
+ case '<<(':
356
+ this._saveContext('<<(', this._graph, this._subject, this._predicate, null);
357
+ this._graph = null;
358
+ return this._readSubject;
331
359
  case '<<':
332
- if (!this._supportsRDFStar)
333
- return this._error('Unexpected RDF-star syntax', token);
334
360
  this._saveContext('<<', this._graph, this._subject, this._predicate, null);
335
361
  this._graph = null;
336
362
  return this._readSubject;
@@ -366,6 +392,10 @@ export default class N3Parser {
366
392
  return this._readBlankNodeTail(token);
367
393
  }
368
394
  else {
395
+ const stack = this._contextStack, parentParent = stack.length > 1 && stack[stack.length - 2];
396
+ if (parentParent.type === '<<') {
397
+ return this._error('Unexpected compound blank node expression in reified triple', token);
398
+ }
369
399
  this._predicate = null;
370
400
  return this._readPredicate(token);
371
401
  }
@@ -475,6 +505,11 @@ export default class N3Parser {
475
505
  this._saveContext('formula', this._graph, this._subject, this._predicate,
476
506
  this._graph = this._factory.blankNode());
477
507
  return this._readSubject;
508
+ case '<<':
509
+ this._saveContext('<<', this._graph, null, null, null);
510
+ this._graph = null;
511
+ next = this._readSubject;
512
+ break;
478
513
  default:
479
514
  if ((item = this._readEntity(token)) === undefined)
480
515
  return;
@@ -484,6 +519,10 @@ export default class N3Parser {
484
519
  if (list === null)
485
520
  this._subject = list = this._factory.blankNode();
486
521
 
522
+ // When reading a reified triple, store the list as subject in the stack, as this will be overridden when reading the triple.
523
+ if (token.type === '<<')
524
+ stack[stack.length - 1].subject = this._subject;
525
+
487
526
  // Is this the first element of the list?
488
527
  if (previousList === null) {
489
528
  // This list is either the subject or the object of its parent
@@ -524,9 +563,10 @@ export default class N3Parser {
524
563
  }
525
564
 
526
565
  // ### `_completeLiteral` completes a literal with an optional datatype or language
527
- _completeLiteral(token) {
566
+ _completeLiteral(token, component) {
528
567
  // Create a simple string literal by default
529
568
  let literal = this._factory.literal(this._literalValue);
569
+ let readCb;
530
570
 
531
571
  switch (token.type) {
532
572
  // Create a datatyped literal
@@ -534,43 +574,82 @@ export default class N3Parser {
534
574
  case 'typeIRI':
535
575
  const datatype = this._readEntity(token);
536
576
  if (datatype === undefined) return; // No datatype means an error occurred
577
+ if (datatype.value === namespaces.rdf.langString || datatype.value === namespaces.rdf.dirLangString) {
578
+ return this._error('Detected illegal (directional) languaged-tagged string with explicit datatype', token);
579
+ }
537
580
  literal = this._factory.literal(this._literalValue, datatype);
538
581
  token = null;
539
582
  break;
540
583
  // Create a language-tagged string
541
584
  case 'langcode':
585
+ if (token.value.length > 8)
586
+ return this._error('Detected language tag of length larger than 8', token);
542
587
  literal = this._factory.literal(this._literalValue, token.value);
588
+ this._literalLanguage = token.value;
543
589
  token = null;
590
+ readCb = this._readDirCode.bind(this, component);
544
591
  break;
545
592
  }
546
593
 
547
- return { token, literal };
594
+ return { token, literal, readCb };
595
+ }
596
+
597
+ _readDirCode(component, listItem, token) {
598
+ // Attempt to read a dircode
599
+ if (token.type === 'dircode') {
600
+ const term = this._factory.literal(this._literalValue, { language: this._literalLanguage, direction: token.value });
601
+ if (component === 'subject')
602
+ this._subject = term;
603
+ else
604
+ this._object = term;
605
+ this._literalLanguage = undefined;
606
+ token = null;
607
+ }
608
+
609
+ if (component === 'subject')
610
+ return token === null ? this._readPredicateOrNamedGraph : this._readPredicateOrNamedGraph(token);
611
+ return this._completeObjectLiteralPost(token, listItem);
548
612
  }
549
613
 
550
614
  // Completes a literal in subject position
551
615
  _completeSubjectLiteral(token) {
552
- this._subject = this._completeLiteral(token).literal;
616
+ const completed = this._completeLiteral(token, 'subject');
617
+ this._subject = completed.literal;
618
+
619
+ // Postpone completion if the literal is only partially completed (such as lang+dir).
620
+ if (completed.readCb)
621
+ return completed.readCb.bind(this, false);
622
+
553
623
  return this._readPredicateOrNamedGraph;
554
624
  }
555
625
 
556
626
  // Completes a literal in object position
557
627
  _completeObjectLiteral(token, listItem) {
558
- const completed = this._completeLiteral(token);
628
+ const completed = this._completeLiteral(token, 'object');
559
629
  if (!completed)
560
630
  return;
631
+
561
632
  this._object = completed.literal;
562
633
 
634
+ // Postpone completion if the literal is only partially completed (such as lang+dir).
635
+ if (completed.readCb)
636
+ return completed.readCb.bind(this, listItem);
637
+
638
+ return this._completeObjectLiteralPost(completed.token, listItem);
639
+ }
640
+
641
+ _completeObjectLiteralPost(token, listItem) {
563
642
  // If this literal was part of a list, write the item
564
643
  // (we could also check the context stack, but passing in a flag is faster)
565
644
  if (listItem)
566
645
  this._emit(this._subject, this.RDF_FIRST, this._object, this._graph);
567
646
  // If the token was consumed, continue with the rest of the input
568
- if (completed.token === null)
647
+ if (token === null)
569
648
  return this._getContextEndReader();
570
649
  // Otherwise, consume the token now
571
650
  else {
572
651
  this._readCallback = this._getContextEndReader();
573
- return this._readCallback(completed.token);
652
+ return this._readCallback(token);
574
653
  }
575
654
  }
576
655
 
@@ -592,7 +671,7 @@ export default class N3Parser {
592
671
 
593
672
  // ### `_readPunctuation` reads punctuation between quads or quad parts
594
673
  _readPunctuation(token) {
595
- let next, graph = this._graph;
674
+ let next, graph = this._graph, startingAnnotation = false;
596
675
  const subject = this._subject, inversePredicate = this._inversePredicate;
597
676
  switch (token.type) {
598
677
  // A closing brace ends a graph
@@ -605,6 +684,7 @@ export default class N3Parser {
605
684
  // A dot just ends the statement, without sharing anything with the next
606
685
  case '.':
607
686
  this._subject = null;
687
+ this._tripleTerm = null;
608
688
  next = this._contextStack.length ? this._readSubject : this._readInTopContext;
609
689
  if (inversePredicate) this._inversePredicate = false;
610
690
  break;
@@ -616,20 +696,24 @@ export default class N3Parser {
616
696
  case ',':
617
697
  next = this._readObject;
618
698
  break;
699
+ // ~ is allowed in the annotation syntax
700
+ case '~':
701
+ next = this._readReifierInAnnotation;
702
+ startingAnnotation = true;
703
+ break;
619
704
  // {| means that the current triple is annotated with predicate-object pairs.
620
705
  case '{|':
621
- if (!this._supportsRDFStar)
622
- return this._error('Unexpected RDF-star syntax', token);
623
- // Continue using the last triple as quoted triple subject for the predicate-object pairs.
624
- const predicate = this._predicate, object = this._object;
625
- this._subject = this._factory.quad(subject, predicate, object, this.DEFAULTGRAPH);
706
+ // Continue using the last triple as reified triple subject for the predicate-object pairs.
707
+ this._subject = this._readTripleTerm();
708
+ startingAnnotation = true;
626
709
  next = this._readPredicate;
627
710
  break;
628
- // |} means that the current quoted triple in annotation syntax is finalized.
711
+ // |} means that the current reified triple in annotation syntax is finalized.
629
712
  case '|}':
630
- if (this._subject.termType !== 'Quad')
631
- return this._error('Unexpected asserted triple closing', token);
713
+ if (!this._annotation)
714
+ return this._error('Unexpected annotation syntax closing', token);
632
715
  this._subject = null;
716
+ this._annotation = false;
633
717
  next = this._readPunctuation;
634
718
  break;
635
719
  default:
@@ -641,13 +725,16 @@ export default class N3Parser {
641
725
  return this._error(`Expected punctuation to follow "${this._object.id}"`, token);
642
726
  }
643
727
  // A quad has been completed now, so return it
644
- if (subject !== null) {
728
+ if (subject !== null && (!startingAnnotation || (startingAnnotation && !this._annotation))) {
645
729
  const predicate = this._predicate, object = this._object;
646
730
  if (!inversePredicate)
647
731
  this._emit(subject, predicate, object, graph);
648
732
  else
649
733
  this._emit(object, predicate, subject, graph);
650
734
  }
735
+ if (startingAnnotation) {
736
+ this._annotation = true;
737
+ }
651
738
  return next;
652
739
  }
653
740
 
@@ -705,6 +792,23 @@ export default class N3Parser {
705
792
  return this._readDeclarationPunctuation;
706
793
  }
707
794
 
795
+ // ### `_isValidVersion` checks if the given version is valid for this parser to handle.
796
+ _isValidVersion(version) {
797
+ return this._parseUnsupportedVersions || N3Parser.SUPPORTED_VERSIONS.includes(version);
798
+ }
799
+
800
+ // ### `_readVersion` reads version string declaration
801
+ _readVersion(token) {
802
+ if (token.type !== 'literal')
803
+ return this._error('Expected literal to follow version declaration', token);
804
+ if ((token.end - token.start) !== token.value.length + 2)
805
+ return this._error('Version declarations must use single quotes', token);
806
+ this._versionCallback(token.value);
807
+ if (!this._isValidVersion(token.value))
808
+ return this._error(`Detected unsupported version: "${token.value}"`, token);
809
+ return this._readDeclarationPunctuation;
810
+ }
811
+
708
812
  // ### `_readNamedGraphLabel` reads the label of a named graph
709
813
  _readNamedGraphLabel(token) {
710
814
  switch (token.type) {
@@ -853,25 +957,15 @@ export default class N3Parser {
853
957
  return this._readPath;
854
958
  }
855
959
 
856
- // ### `_readRDFStarTailOrGraph` reads the graph of a nested RDF-star quad or the end of a nested RDF-star triple
857
- _readRDFStarTailOrGraph(token) {
858
- if (token.type !== '>>') {
859
- // An entity means this is a quad (only allowed if not already inside a graph)
860
- if (this._supportsQuads && this._graph === null && (this._graph = this._readEntity(token)) !== undefined)
861
- return this._readRDFStarTail;
862
- return this._error(`Expected >> to follow "${this._object.id}"`, token);
863
- }
864
- return this._readRDFStarTail(token);
865
- }
866
-
867
- // ### `_readRDFStarTail` reads the end of a nested RDF-star triple
868
- _readRDFStarTail(token) {
869
- if (token.type !== '>>')
870
- return this._error(`Expected >> but got ${token.type}`, token);
960
+ // ### `_readTripleTermTail` reads the end of a triple term
961
+ _readTripleTermTail(token) {
962
+ if (token.type !== ')>>')
963
+ return this._error(`Expected )>> but got ${token.type}`, token);
871
964
  // Read the quad and restore the previous context
872
965
  const quad = this._factory.quad(this._subject, this._predicate, this._object,
873
- this._graph || this.DEFAULTGRAPH);
874
- this._restoreContext('<<', token);
966
+ this._graph || this.DEFAULTGRAPH);
967
+ this._restoreContext('<<(', token);
968
+
875
969
  // If the triple was the subject, continue by reading the predicate.
876
970
  if (this._subject === null) {
877
971
  this._subject = quad;
@@ -884,6 +978,78 @@ export default class N3Parser {
884
978
  }
885
979
  }
886
980
 
981
+ // ### `_readReifiedTripleTailOrReifier` reads a reifier or the end of a nested reified triple
982
+ _readReifiedTripleTailOrReifier(token) {
983
+ if (token.type === '~') {
984
+ return this._readReifier;
985
+ }
986
+ return this._readReifiedTripleTail(token);
987
+ }
988
+
989
+ // ### `_readReifiedTripleTail` reads the end of a nested reified triple
990
+ _readReifiedTripleTail(token) {
991
+ if (token.type !== '>>')
992
+ return this._error(`Expected >> but got ${token.type}`, token);
993
+ // Read the triple term and restore the previous context
994
+ this._tripleTerm = null;
995
+ const reifier = this._readTripleTerm();
996
+ this._restoreContext('<<', token);
997
+
998
+ // // If we're in a list, continue processing that list
999
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
1000
+ if (parent && parent.type === 'list') {
1001
+ this._emit(this._subject, this.RDF_FIRST, reifier, this._graph);
1002
+ return this._getContextEndReader();
1003
+ }
1004
+ // If the triple was the subject, continue by reading the predicate.
1005
+ else if (this._subject === null) {
1006
+ this._subject = reifier;
1007
+ return this._readPredicateOrReifierTripleEnd;
1008
+ }
1009
+ // If the triple was the object, read context end.
1010
+ else {
1011
+ this._object = reifier;
1012
+ return this._getContextEndReader();
1013
+ }
1014
+ }
1015
+
1016
+ _readPredicateOrReifierTripleEnd(token) {
1017
+ if (token.type === '.') {
1018
+ this._subject = null;
1019
+ return this._readPunctuation(token);
1020
+ }
1021
+ return this._readPredicate(token);
1022
+ }
1023
+
1024
+ // ### `_readReifier` reads the triple term identifier after a tilde when in a reifying triple.
1025
+ _readReifier(token) {
1026
+ this._reifier = this._readEntity(token);
1027
+ return this._readReifiedTripleTail;
1028
+ }
1029
+
1030
+ // ### `_readReifier` reads the optional triple term identifier after a tilde when in annotation syntax.
1031
+ _readReifierInAnnotation(token) {
1032
+ // If next token is a reifier, read it as such.
1033
+ if (token.type === 'IRI' || token.type === 'typeIRI' || token.type === 'type' || token.type === 'prefixed' || token.type === 'blank' || token.type === 'var') {
1034
+ this._reifier = this._readEntity(token);
1035
+ return this._readPunctuation;
1036
+ }
1037
+ // Otherwise, emit and assert triple term.
1038
+ this._readTripleTerm();
1039
+ this._subject = null;
1040
+ return this._readPunctuation(token);
1041
+ }
1042
+
1043
+ _readTripleTerm() {
1044
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
1045
+ const parentGraph = parent ? parent.graph : undefined;
1046
+ const reifier = this._reifier || this._factory.blankNode();
1047
+ this._reifier = null;
1048
+ this._tripleTerm = this._tripleTerm || this._factory.quad(this._subject, this._predicate, this._object);
1049
+ this._emit(reifier, this.RDF_REIFIES, this._tripleTerm, parentGraph || this.DEFAULTGRAPH);
1050
+ return reifier;
1051
+ }
1052
+
887
1053
  // ### `_getContextEndReader` gets the next reader function at the end of a context
888
1054
  _getContextEndReader() {
889
1055
  const contextStack = this._contextStack;
@@ -897,8 +1063,10 @@ export default class N3Parser {
897
1063
  return this._readListItem;
898
1064
  case 'formula':
899
1065
  return this._readFormulaTail;
1066
+ case '<<(':
1067
+ return this._readTripleTermTail;
900
1068
  case '<<':
901
- return this._readRDFStarTailOrGraph;
1069
+ return this._readReifiedTripleTailOrReifier;
902
1070
  }
903
1071
  }
904
1072
 
@@ -1013,27 +1181,30 @@ export default class N3Parser {
1013
1181
  // ## Public methods
1014
1182
 
1015
1183
  // ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
1016
- parse(input, quadCallback, prefixCallback) {
1184
+ parse(input, quadCallback, prefixCallback, versionCallback) {
1017
1185
  // The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
1018
1186
  // As a second and third parameter it still accepts a separate quadCallback and prefixCallback for backward compatibility as well
1019
- let onQuad, onPrefix, onComment;
1020
- if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment)) {
1187
+ let onQuad, onPrefix, onComment, onVersion;
1188
+ if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
1021
1189
  onQuad = quadCallback.onQuad;
1022
1190
  onPrefix = quadCallback.onPrefix;
1023
1191
  onComment = quadCallback.onComment;
1192
+ onVersion = quadCallback.onVersion;
1024
1193
  }
1025
1194
  else {
1026
1195
  onQuad = quadCallback;
1027
1196
  onPrefix = prefixCallback;
1197
+ onVersion = versionCallback;
1028
1198
  }
1029
1199
  // The read callback is the next function to be executed when a token arrives.
1030
1200
  // We start reading in the top context.
1031
- this._readCallback = this._readInTopContext;
1201
+ this._readCallback = this._readBeforeTopContext;
1032
1202
  this._sparqlStyle = false;
1033
1203
  this._prefixes = Object.create(null);
1034
1204
  this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
1035
1205
  : `b${blankNodePrefix++}_`;
1036
1206
  this._prefixCallback = onPrefix || noop;
1207
+ this._versionCallback = onVersion || noop;
1037
1208
  this._inversePredicate = false;
1038
1209
  this._quantified = Object.create(null);
1039
1210
 
@@ -1089,17 +1260,22 @@ function initDataFactory(parser, factory) {
1089
1260
  parser.DEFAULTGRAPH = factory.defaultGraph();
1090
1261
 
1091
1262
  // Set common named nodes
1092
- parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
1093
- parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
1094
- parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
1095
- parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
1096
- parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
1263
+ parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
1264
+ parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
1265
+ parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
1266
+ parser.RDF_REIFIES = factory.namedNode(namespaces.rdf.reifies);
1267
+ parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
1268
+ parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
1097
1269
  parser.ABBREVIATIONS = {
1098
1270
  'a': factory.namedNode(namespaces.rdf.type),
1099
1271
  '=': factory.namedNode(namespaces.owl.sameAs),
1100
1272
  '>': factory.namedNode(namespaces.log.implies),
1101
- '<': factory.namedNode(namespaces.log.isImpliedBy),
1102
1273
  };
1103
1274
  parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
1104
1275
  }
1276
+ N3Parser.SUPPORTED_VERSIONS = [
1277
+ '1.2',
1278
+ '1.2-basic',
1279
+ '1.1',
1280
+ ];
1105
1281
  initDataFactory(N3Parser.prototype, N3DataFactory);
package/src/N3Store.js CHANGED
@@ -163,7 +163,7 @@ export default class N3Store {
163
163
  this._graphs = Object.create(null);
164
164
 
165
165
  // Shift parameters if `quads` is not given
166
- if (!options && quads && !quads[0] && !(typeof quads.match === 'function'))
166
+ if (!options && quads && !quads[0])
167
167
  options = quads, quads = null;
168
168
  options = options || {};
169
169
  this._factory = options.factory || N3DataFactory;
@@ -175,7 +175,7 @@ export default class N3Store {
175
175
 
176
176
  // Add quads if passed
177
177
  if (quads)
178
- this.addAll(quads);
178
+ this.addQuads(quads);
179
179
  }
180
180
 
181
181
  // ## Public properties
@@ -601,7 +601,7 @@ export default class N3Store {
601
601
  // Setting any field to `undefined` or `null` indicates a wildcard.
602
602
  some(callback, subject, predicate, object, graph) {
603
603
  for (const quad of this.readQuads(subject, predicate, object, graph))
604
- if (callback(quad, this))
604
+ if (callback(quad))
605
605
  return true;
606
606
  return false;
607
607
  }
@@ -1134,28 +1134,27 @@ class DatasetCoreAndReadableStream extends Readable {
1134
1134
 
1135
1135
  const graphs = n3Store._getGraphs(graph);
1136
1136
  for (const graphKey in graphs) {
1137
- let subjects, predicates, objects, content;
1138
- if (content = graphs[graphKey]) {
1139
- if (!subjectId && predicateId) {
1140
- if (predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId])) {
1141
- subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1142
- objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1143
- }
1144
- }
1145
- else if (objectId) {
1146
- if (objects = indexMatch(content.objects, [objectId, subjectId, predicateId])) {
1147
- subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1148
- predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1149
- }
1137
+ let subjects, predicates, objects;
1138
+
1139
+ if (!subjectId && predicateId) {
1140
+ if (predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId])) {
1141
+ subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1142
+ objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1150
1143
  }
1151
- else if (subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId])) {
1152
- predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1153
- objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1144
+ }
1145
+ else if (objectId) {
1146
+ if (objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId])) {
1147
+ subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1148
+ predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1154
1149
  }
1155
-
1156
- if (subjects)
1157
- newStore._graphs[graphKey] = { subjects, predicates, objects };
1158
1150
  }
1151
+ else if (subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId])) {
1152
+ predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1153
+ objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1154
+ }
1155
+
1156
+ if (subjects)
1157
+ newStore._graphs[graphKey] = { subjects, predicates, objects };
1159
1158
  }
1160
1159
  newStore._size = null;
1161
1160
  }
package/src/N3Util.js CHANGED
@@ -22,11 +22,6 @@ export function isVariable(term) {
22
22
  return !!term && term.termType === 'Variable';
23
23
  }
24
24
 
25
- // Tests whether the given term represents a quad
26
- export function isQuad(term) {
27
- return !!term && term.termType === 'Quad';
28
- }
29
-
30
25
  // Tests whether the given term represents the default graph
31
26
  export function isDefaultGraph(term) {
32
27
  return !!term && term.termType === 'DefaultGraph';
package/src/N3Writer.js CHANGED
@@ -2,8 +2,6 @@
2
2
  import namespaces from './IRIs';
3
3
  import { default as N3DataFactory, Term } from './N3DataFactory';
4
4
  import { isDefaultGraph } from './N3Util';
5
- import BaseIRI from './BaseIRI';
6
- import { escapeRegex } from './Util';
7
5
 
8
6
  const DEFAULTGRAPH = N3DataFactory.defaultGraph();
9
7
 
@@ -60,7 +58,9 @@ export default class N3Writer {
60
58
  this._prefixIRIs = Object.create(null);
61
59
  options.prefixes && this.addPrefixes(options.prefixes);
62
60
  if (options.baseIRI) {
63
- this._baseIri = new BaseIRI(options.baseIRI);
61
+ this._baseMatcher = new RegExp(`^${escapeRegex(options.baseIRI)
62
+ }${options.baseIRI.endsWith('/') ? '' : '[#?]'}`);
63
+ this._baseLength = options.baseIRI.length;
64
64
  }
65
65
  }
66
66
  else {
@@ -153,9 +153,8 @@ export default class N3Writer {
153
153
  }
154
154
  let iri = entity.value;
155
155
  // Use relative IRIs if requested and possible
156
- if (this._baseIri) {
157
- iri = this._baseIri.toRelative(iri);
158
- }
156
+ if (this._baseMatcher && this._baseMatcher.test(iri))
157
+ iri = iri.substr(this._baseLength);
159
158
  // Escape special characters
160
159
  if (escape.test(iri))
161
160
  iri = iri.replace(escapeAll, characterReplacer);
@@ -173,8 +172,9 @@ export default class N3Writer {
173
172
  value = value.replace(escapeAll, characterReplacer);
174
173
 
175
174
  // Write a language-tagged literal
175
+ const direction = literal.direction ? `--${literal.direction}` : '';
176
176
  if (literal.language)
177
- return `"${value}"@${literal.language}`;
177
+ return `"${value}"@${literal.language}${direction}`;
178
178
 
179
179
  // Write dedicated literals per data type
180
180
  if (this._lineMode) {
@@ -395,3 +395,7 @@ function characterReplacer(character) {
395
395
  }
396
396
  return result;
397
397
  }
398
+
399
+ function escapeRegex(regex) {
400
+ return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
401
+ }
package/src/index.js CHANGED
@@ -7,7 +7,6 @@ import Reasoner, { getRulesFromDataset } from './N3Reasoner';
7
7
  import StreamParser from './N3StreamParser';
8
8
  import StreamWriter from './N3StreamWriter';
9
9
  import * as Util from './N3Util';
10
- import BaseIRI from './BaseIRI';
11
10
 
12
11
  import {
13
12
  default as DataFactory,
@@ -37,7 +36,6 @@ export {
37
36
  StreamWriter,
38
37
  Util,
39
38
  Reasoner,
40
- BaseIRI,
41
39
 
42
40
  DataFactory,
43
41
 
@@ -67,7 +65,6 @@ export default {
67
65
  StreamWriter,
68
66
  Util,
69
67
  Reasoner,
70
- BaseIRI,
71
68
 
72
69
  DataFactory,
73
70