n3 2.0.0-beta.1 → 2.0.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/BaseIRI.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _Util = require("./Util");
8
+ // Do not handle base IRIs without scheme, and currently unsupported cases:
9
+ // - file: IRIs (which could also use backslashes)
10
+ // - IRIs containing /. or /.. or //
11
+ const BASE_UNSUPPORTED = /^:?[^:?#]*(?:[?#]|$)|^file:|^[^:]*:\/*[^?#]+?\/(?:\.\.?(?:\/|$)|\/)/i;
12
+ const SUFFIX_SUPPORTED = /^(?:(?:[^/?#]{3,}|\.?[^/?#.]\.?)(?:\/[^/?#]{3,}|\.?[^/?#.]\.?)*\/?)?(?:[?#]|$)/;
13
+ const CURRENT = './';
14
+ const PARENT = '../';
15
+ const QUERY = '?';
16
+ const FRAGMENT = '#';
17
+ class BaseIRI {
18
+ constructor(base) {
19
+ this.base = base;
20
+ this._baseLength = 0;
21
+ this._baseMatcher = null;
22
+ this._pathReplacements = new Array(base.length + 1);
23
+ }
24
+ static supports(base) {
25
+ return !BASE_UNSUPPORTED.test(base);
26
+ }
27
+ _getBaseMatcher() {
28
+ if (this._baseMatcher) return this._baseMatcher;
29
+ if (!BaseIRI.supports(this.base)) return this._baseMatcher = /.^/;
30
+
31
+ // Extract the scheme
32
+ const scheme = /^[^:]*:\/*/.exec(this.base)[0];
33
+ const regexHead = ['^', (0, _Util.escapeRegex)(scheme)];
34
+ const regexTail = [];
35
+
36
+ // Generate a regex for every path segment
37
+ const segments = [],
38
+ segmenter = /[^/?#]*([/?#])/y;
39
+ let segment,
40
+ query = 0,
41
+ fragment = 0,
42
+ last = segmenter.lastIndex = scheme.length;
43
+ while (!query && !fragment && (segment = segmenter.exec(this.base))) {
44
+ // Truncate base resolution path at fragment start
45
+ if (segment[1] === FRAGMENT) fragment = segmenter.lastIndex - 1;else {
46
+ // Create regex that matches the segment
47
+ regexHead.push((0, _Util.escapeRegex)(segment[0]), '(?:');
48
+ regexTail.push(')?');
49
+
50
+ // Create dedicated query string replacement
51
+ if (segment[1] !== QUERY) segments.push(last = segmenter.lastIndex);else {
52
+ query = last = segmenter.lastIndex;
53
+ fragment = this.base.indexOf(FRAGMENT, query);
54
+ this._pathReplacements[query] = QUERY;
55
+ }
56
+ }
57
+ }
58
+
59
+ // Precalculate parent path substitutions
60
+ for (let i = 0; i < segments.length; i++) this._pathReplacements[segments[i]] = PARENT.repeat(segments.length - i - 1);
61
+ this._pathReplacements[segments[segments.length - 1]] = CURRENT;
62
+
63
+ // Add the remainder of the base IRI (without fragment) to the regex
64
+ this._baseLength = fragment > 0 ? fragment : this.base.length;
65
+ regexHead.push((0, _Util.escapeRegex)(this.base.substring(last, this._baseLength)), query ? '(?:#|$)' : '(?:[?#]|$)');
66
+ return this._baseMatcher = new RegExp([...regexHead, ...regexTail].join(''));
67
+ }
68
+ toRelative(iri) {
69
+ // Unsupported or non-matching base IRI
70
+ const match = this._getBaseMatcher().exec(iri);
71
+ if (!match) return iri;
72
+
73
+ // Exact base IRI match
74
+ const length = match[0].length;
75
+ if (length === this._baseLength && length === iri.length) return '';
76
+
77
+ // Parent path match
78
+ const parentPath = this._pathReplacements[length];
79
+ if (parentPath) {
80
+ const suffix = iri.substring(length);
81
+ // Don't abbreviate unsupported path
82
+ if (parentPath !== QUERY && !SUFFIX_SUPPORTED.test(suffix)) return iri;
83
+ // Omit ./ with fragment or query string
84
+ if (parentPath === CURRENT && /^[^?#]/.test(suffix)) return suffix;
85
+ // Append suffix to relative parent path
86
+ return parentPath + suffix;
87
+ }
88
+
89
+ // Fragment or query string, so include delimiter
90
+ return iri.substring(length - 1);
91
+ }
92
+ }
93
+ exports.default = BaseIRI;
package/lib/IRIs.js CHANGED
@@ -32,6 +32,7 @@ var _default = exports.default = {
32
32
  forAll: `${SWAP}reify#forAll`
33
33
  },
34
34
  log: {
35
- implies: `${SWAP}log#implies`
35
+ implies: `${SWAP}log#implies`,
36
+ isImpliedBy: `${SWAP}log#isImpliedBy`
36
37
  }
37
38
  };
package/lib/N3Lexer.js CHANGED
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _buffer = require("buffer");
8
- var _queueMicrotask = _interopRequireDefault(require("queue-microtask"));
9
8
  var _IRIs = _interopRequireDefault(require("./IRIs"));
10
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
10
  // **N3Lexer** tokenizes N3 documents.
@@ -86,6 +85,9 @@ class N3Lexer {
86
85
  this._endOfFile = /^(?:#[^\n\r]*)?$/;
87
86
  options = options || {};
88
87
 
88
+ // Whether the log:isImpliedBy predicate is supported
89
+ this._isImpliedBy = options.isImpliedBy;
90
+
89
91
  // In line mode (N-Triples or N-Quads), only simple features may be parsed
90
92
  if (this._lineMode = !!options.lineMode) {
91
93
  this._n3Mode = false;
@@ -183,7 +185,10 @@ class N3Lexer {
183
185
  // Try to find a reified triple
184
186
  else if (!this._lineMode && input.length > (inputFinished ? 1 : 2) && input[1] === '<') type = '<<', matchLength = 2;
185
187
  // Try to find a backwards implication arrow
186
- else if (this._n3Mode && input.length > 1 && input[1] === '=') type = 'inverse', matchLength = 2, value = '>';
188
+ else if (this._n3Mode && input.length > 1 && input[1] === '=') {
189
+ matchLength = 2;
190
+ if (this._isImpliedBy) type = 'abbreviation', value = '<';else type = 'inverse', value = '>';
191
+ }
187
192
  break;
188
193
  case '>':
189
194
  // Try to find a reified triple
@@ -492,7 +497,7 @@ class N3Lexer {
492
497
  if (typeof input === 'string') {
493
498
  this._input = this._readStartingBom(input);
494
499
  // If a callback was passed, asynchronously call it
495
- if (typeof callback === 'function') (0, _queueMicrotask.default)(() => this._tokenizeToEnd(callback, true));
500
+ if (typeof callback === 'function') queueMicrotask(() => this._tokenizeToEnd(callback, true));
496
501
  // If no callback was passed, tokenize synchronously and return
497
502
  else {
498
503
  const tokens = [];
package/lib/N3Parser.js CHANGED
@@ -34,6 +34,8 @@ class N3Parser {
34
34
  if (!(this._supportsNamedGraphs = !(isTurtle || isN3))) this._readPredicateOrNamedGraph = this._readPredicate;
35
35
  // Support triples in other graphs
36
36
  this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
37
+ // Whether the log:isImpliedBy predicate is supported
38
+ this._isImpliedBy = options.isImpliedBy;
37
39
  // Disable relative IRIs in N-Triples or N-Quads mode
38
40
  if (isLineMode) this._resolveRelativeIRI = iri => {
39
41
  return null;
@@ -41,10 +43,14 @@ class N3Parser {
41
43
  this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' : options.blankNodePrefix.replace(/^(?!_:)/, '_:');
42
44
  this._lexer = options.lexer || new _N3Lexer.default({
43
45
  lineMode: isLineMode,
44
- n3: isN3
46
+ n3: isN3,
47
+ isImpliedBy: this._isImpliedBy
45
48
  });
46
49
  // Disable explicit quantifiers by default
47
50
  this._explicitQuantifiers = !!options.explicitQuantifiers;
51
+ // Disable parsing of unsupported versions by default
52
+ this._parseUnsupportedVersions = !!options.parseUnsupportedVersions;
53
+ this._version = options.version;
48
54
  }
49
55
 
50
56
  // ## Static class methods
@@ -121,6 +127,12 @@ class N3Parser {
121
127
  }
122
128
  }
123
129
 
130
+ // ### `_readBeforeTopContext` is called once only at the start of parsing.
131
+ _readBeforeTopContext(token) {
132
+ if (this._version && !this._isValidVersion(this._version)) return this._error(`Detected unsupported version as media type parameter: "${this._version}"`, token);
133
+ return this._readInTopContext(token);
134
+ }
135
+
124
136
  // ### `_readInTopContext` reads a token when in the top context
125
137
  _readInTopContext(token) {
126
138
  switch (token.type) {
@@ -291,6 +303,7 @@ class N3Parser {
291
303
  default:
292
304
  if ((this._predicate = this._readEntity(token)) === undefined) return;
293
305
  }
306
+ this._validAnnotation = true;
294
307
  // The next token must be an object
295
308
  return this._readObject;
296
309
  }
@@ -648,12 +661,14 @@ class N3Parser {
648
661
  case '{|':
649
662
  // Continue using the last triple as reified triple subject for the predicate-object pairs.
650
663
  this._subject = this._readTripleTerm();
664
+ this._validAnnotation = false;
651
665
  startingAnnotation = true;
652
666
  next = this._readPredicate;
653
667
  break;
654
668
  // |} means that the current reified triple in annotation syntax is finalized.
655
669
  case '|}':
656
670
  if (!this._annotation) return this._error('Unexpected annotation syntax closing', token);
671
+ if (!this._validAnnotation) return this._error('Annotation block can not be empty', token);
657
672
  this._subject = null;
658
673
  this._annotation = false;
659
674
  next = this._readPunctuation;
@@ -728,11 +743,17 @@ class N3Parser {
728
743
  return this._readDeclarationPunctuation;
729
744
  }
730
745
 
746
+ // ### `_isValidVersion` checks if the given version is valid for this parser to handle.
747
+ _isValidVersion(version) {
748
+ return this._parseUnsupportedVersions || N3Parser.SUPPORTED_VERSIONS.includes(version);
749
+ }
750
+
731
751
  // ### `_readVersion` reads version string declaration
732
752
  _readVersion(token) {
733
753
  if (token.type !== 'literal') return this._error('Expected literal to follow version declaration', token);
734
754
  if (token.end - token.start !== token.value.length + 2) return this._error('Version declarations must use single quotes', token);
735
- this._prefixCallback(token.value);
755
+ this._versionCallback(token.value);
756
+ if (!this._isValidVersion(token.value)) return this._error(`Detected unsupported version: "${token.value}"`, token);
736
757
  return this._readDeclarationPunctuation;
737
758
  }
738
759
 
@@ -1106,7 +1127,7 @@ class N3Parser {
1106
1127
  }
1107
1128
  // The read callback is the next function to be executed when a token arrives.
1108
1129
  // We start reading in the top context.
1109
- this._readCallback = this._readInTopContext;
1130
+ this._readCallback = this._readBeforeTopContext;
1110
1131
  this._sparqlStyle = false;
1111
1132
  this._prefixes = Object.create(null);
1112
1133
  this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2) : `b${blankNodePrefix++}_`;
@@ -1169,8 +1190,10 @@ function initDataFactory(parser, factory) {
1169
1190
  parser.ABBREVIATIONS = {
1170
1191
  'a': factory.namedNode(_IRIs.default.rdf.type),
1171
1192
  '=': factory.namedNode(_IRIs.default.owl.sameAs),
1172
- '>': factory.namedNode(_IRIs.default.log.implies)
1193
+ '>': factory.namedNode(_IRIs.default.log.implies),
1194
+ '<': factory.namedNode(_IRIs.default.log.isImpliedBy)
1173
1195
  };
1174
1196
  parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
1175
1197
  }
1198
+ N3Parser.SUPPORTED_VERSIONS = ['1.2', '1.2-basic', '1.1'];
1176
1199
  initDataFactory(N3Parser.prototype, _N3DataFactory.default);
package/lib/N3Store.js CHANGED
@@ -10,8 +10,7 @@ var _IRIs = _interopRequireDefault(require("./IRIs"));
10
10
  var _N3Util = require("./N3Util");
11
11
  var _N3Writer = _interopRequireDefault(require("./N3Writer"));
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
14
  // **N3Store** objects store N3 quads by graph in memory.
16
15
 
17
16
  const ITERATOR = Symbol('iter');
@@ -147,7 +146,7 @@ class N3Store {
147
146
  this._graphs = Object.create(null);
148
147
 
149
148
  // Shift parameters if `quads` is not given
150
- if (!options && quads && !quads[0]) options = quads, quads = null;
149
+ if (!options && quads && !quads[0] && !(typeof quads.match === 'function')) options = quads, quads = null;
151
150
  options = options || {};
152
151
  this._factory = options.factory || _N3DataFactory.default;
153
152
  this._entityIndex = options.entityIndex || new N3EntityIndex({
@@ -159,7 +158,7 @@ class N3Store {
159
158
  this._termToNewNumericId = this._entityIndex._termToNewNumericId.bind(this._entityIndex);
160
159
 
161
160
  // Add quads if passed
162
- if (quads) this.addQuads(quads);
161
+ if (quads) this.addAll(quads);
163
162
  }
164
163
 
165
164
  // ## Public properties
@@ -579,7 +578,7 @@ class N3Store {
579
578
  // and returns `true` if it returns truthy for any of them.
580
579
  // Setting any field to `undefined` or `null` indicates a wildcard.
581
580
  some(callback, subject, predicate, object, graph) {
582
- for (const quad of this.readQuads(subject, predicate, object, graph)) if (callback(quad)) return true;
581
+ for (const quad of this.readQuads(subject, predicate, object, graph)) if (callback(quad, this)) return true;
583
582
  return false;
584
583
  }
585
584
 
@@ -1083,26 +1082,28 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
1083
1082
  if (subject && !(subjectId = newStore._termToNumericId(subject)) || predicate && !(predicateId = newStore._termToNumericId(predicate)) || object && !(objectId = newStore._termToNumericId(object))) return newStore;
1084
1083
  const graphs = n3Store._getGraphs(graph);
1085
1084
  for (const graphKey in graphs) {
1086
- let subjects, predicates, objects;
1087
- if (!subjectId && predicateId) {
1088
- if (predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId])) {
1089
- subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1090
- objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1091
- }
1092
- } else if (objectId) {
1093
- if (objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId])) {
1094
- subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1095
- predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1085
+ let subjects, predicates, objects, content;
1086
+ if (content = graphs[graphKey]) {
1087
+ if (!subjectId && predicateId) {
1088
+ if (predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId])) {
1089
+ subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1090
+ objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1091
+ }
1092
+ } else if (objectId) {
1093
+ if (objects = indexMatch(content.objects, [objectId, subjectId, predicateId])) {
1094
+ subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1095
+ predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1096
+ }
1097
+ } else if (subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId])) {
1098
+ predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1099
+ objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1096
1100
  }
1097
- } else if (subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId])) {
1098
- predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1099
- objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1101
+ if (subjects) newStore._graphs[graphKey] = {
1102
+ subjects,
1103
+ predicates,
1104
+ objects
1105
+ };
1100
1106
  }
1101
- if (subjects) newStore._graphs[graphKey] = {
1102
- subjects,
1103
- predicates,
1104
- objects
1105
- };
1106
1107
  }
1107
1108
  newStore._size = null;
1108
1109
  }
package/lib/N3Util.js CHANGED
@@ -8,6 +8,7 @@ exports.isBlankNode = isBlankNode;
8
8
  exports.isDefaultGraph = isDefaultGraph;
9
9
  exports.isLiteral = isLiteral;
10
10
  exports.isNamedNode = isNamedNode;
11
+ exports.isQuad = isQuad;
11
12
  exports.isVariable = isVariable;
12
13
  exports.prefix = prefix;
13
14
  exports.prefixes = prefixes;
@@ -35,6 +36,11 @@ function isVariable(term) {
35
36
  return !!term && term.termType === 'Variable';
36
37
  }
37
38
 
39
+ // Tests whether the given term represents a quad
40
+ function isQuad(term) {
41
+ return !!term && term.termType === 'Quad';
42
+ }
43
+
38
44
  // Tests whether the given term represents the default graph
39
45
  function isDefaultGraph(term) {
40
46
  return !!term && term.termType === 'DefaultGraph';
package/lib/N3Writer.js CHANGED
@@ -7,8 +7,9 @@ exports.default = void 0;
7
7
  var _IRIs = _interopRequireDefault(require("./IRIs"));
8
8
  var _N3DataFactory = _interopRequireWildcard(require("./N3DataFactory"));
9
9
  var _N3Util = require("./N3Util");
10
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ var _BaseIRI = _interopRequireDefault(require("./BaseIRI"));
11
+ var _Util = require("./Util");
12
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  // **N3Writer** writes N3 documents.
14
15
 
@@ -77,8 +78,7 @@ class N3Writer {
77
78
  this._prefixIRIs = Object.create(null);
78
79
  options.prefixes && this.addPrefixes(options.prefixes);
79
80
  if (options.baseIRI) {
80
- this._baseMatcher = new RegExp(`^${escapeRegex(options.baseIRI)}${options.baseIRI.endsWith('/') ? '' : '[#?]'}`);
81
- this._baseLength = options.baseIRI.length;
81
+ this._baseIri = new _BaseIRI.default(options.baseIRI);
82
82
  }
83
83
  } else {
84
84
  this._lineMode = true;
@@ -156,7 +156,9 @@ class N3Writer {
156
156
  }
157
157
  let iri = entity.value;
158
158
  // Use relative IRIs if requested and possible
159
- if (this._baseMatcher && this._baseMatcher.test(iri)) iri = iri.substr(this._baseLength);
159
+ if (this._baseIri) {
160
+ iri = this._baseIri.toRelative(iri);
161
+ }
160
162
  // Escape special characters
161
163
  if (escape.test(iri)) iri = iri.replace(escapeAll, characterReplacer);
162
164
  // Try to represent the IRI as prefixed name
@@ -226,7 +228,7 @@ class N3Writer {
226
228
  object,
227
229
  graph
228
230
  }) {
229
- return `<<${this._encodeSubject(subject)} ${this._encodePredicate(predicate)} ${this._encodeObject(object)}${(0, _N3Util.isDefaultGraph)(graph) ? '' : ` ${this._encodeIriOrBlank(graph)}`}>>`;
231
+ return `<<(${this._encodeSubject(subject)} ${this._encodePredicate(predicate)} ${this._encodeObject(object)}${(0, _N3Util.isDefaultGraph)(graph) ? '' : ` ${this._encodeIriOrBlank(graph)}`})>>`;
230
232
  }
231
233
 
232
234
  // ### `_blockedWrite` replaces `_write` after the writer has been closed
@@ -284,7 +286,7 @@ class N3Writer {
284
286
  IRIlist += IRIlist ? `|${prefixIRI}` : prefixIRI;
285
287
  prefixList += (prefixList ? '|' : '') + this._prefixIRIs[prefixIRI];
286
288
  }
287
- IRIlist = escapeRegex(IRIlist, /[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
289
+ IRIlist = (0, _Util.escapeRegex)(IRIlist, /[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
288
290
  this._prefixRegex = new RegExp(`^(?:${prefixList})[^\/]*$|` + `^(${IRIlist})([_a-zA-Z0-9][\\-_a-zA-Z0-9]*)$`);
289
291
  }
290
292
  // End a prefix block with a newline
@@ -380,7 +382,4 @@ function characterReplacer(character) {
380
382
  }
381
383
  }
382
384
  return result;
383
- }
384
- function escapeRegex(regex) {
385
- return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
386
385
  }
package/lib/Util.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.escapeRegex = escapeRegex;
7
+ function escapeRegex(regex) {
8
+ return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
9
+ }
package/lib/index.js CHANGED
@@ -3,6 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "BaseIRI", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _BaseIRI.default;
10
+ }
11
+ });
6
12
  Object.defineProperty(exports, "BlankNode", {
7
13
  enumerable: true,
8
14
  get: function () {
@@ -141,9 +147,9 @@ var _N3StreamParser = _interopRequireDefault(require("./N3StreamParser"));
141
147
  var _N3StreamWriter = _interopRequireDefault(require("./N3StreamWriter"));
142
148
  var Util = _interopRequireWildcard(require("./N3Util"));
143
149
  exports.Util = Util;
150
+ var _BaseIRI = _interopRequireDefault(require("./BaseIRI"));
144
151
  var _N3DataFactory = _interopRequireWildcard(require("./N3DataFactory"));
145
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
146
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
152
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
147
153
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
148
154
  // Named exports
149
155
  // Export all named exports as a default object for backward compatibility
@@ -158,6 +164,7 @@ var _default = exports.default = {
158
164
  StreamWriter: _N3StreamWriter.default,
159
165
  Util,
160
166
  Reasoner: _N3Reasoner.default,
167
+ BaseIRI: _BaseIRI.default,
161
168
  DataFactory: _N3DataFactory.default,
162
169
  Term: _N3DataFactory.Term,
163
170
  NamedNode: _N3DataFactory.NamedNode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
@@ -25,7 +25,6 @@
25
25
  ],
26
26
  "dependencies": {
27
27
  "buffer": "^6.0.3",
28
- "queue-microtask": "^1.1.2",
29
28
  "readable-stream": "^4.0.0"
30
29
  },
31
30
  "devDependencies": {
@@ -43,7 +42,7 @@
43
42
  "eslint-plugin-jest": "^28.8.3",
44
43
  "jest": "^29.7.0",
45
44
  "pre-commit": "^1.2.2",
46
- "rdf-isomorphic": "^1.3.1",
45
+ "rdf-isomorphic": "^2.0.0",
47
46
  "rdf-test-suite": "^1.25.0",
48
47
  "streamify-string": "^1.0.1",
49
48
  "uglify-js": "^3.14.3"
@@ -60,8 +59,8 @@
60
59
  "spec-1-1-earl": "npm run spec-1-1-earl-turtle && npm run spec-1-1-earl-ntriples && npm run spec-1-1-earl-nquads && npm run spec-1-1-earl-trig",
61
60
  "spec-1-1-ntriples": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-triples/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/",
62
61
  "spec-1-1-nquads": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/",
63
- "spec-1-1-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/",
64
- "spec-1-1-trig": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-trig/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/",
62
+ "spec-1-1-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/ --skip \"(bad-numeric-escape|bareword_decimal)\"",
63
+ "spec-1-1-trig": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-trig/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/ --skip \"(bad-numeric-escape|IRI-resolution-01)\"",
65
64
  "spec-1-1-earl-ntriples": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-triples/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-ntriples.ttl",
66
65
  "spec-1-1-earl-nquads": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-nquads.ttl",
67
66
  "spec-1-1-earl-turtle": "rdf-test-suite spec/parser.js https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/ -o earl -p spec/earl-meta.json > spec/earl-turtle.ttl",
package/src/BaseIRI.js ADDED
@@ -0,0 +1,101 @@
1
+ import { escapeRegex } from './Util';
2
+
3
+ // Do not handle base IRIs without scheme, and currently unsupported cases:
4
+ // - file: IRIs (which could also use backslashes)
5
+ // - IRIs containing /. or /.. or //
6
+ const BASE_UNSUPPORTED = /^:?[^:?#]*(?:[?#]|$)|^file:|^[^:]*:\/*[^?#]+?\/(?:\.\.?(?:\/|$)|\/)/i;
7
+ const SUFFIX_SUPPORTED = /^(?:(?:[^/?#]{3,}|\.?[^/?#.]\.?)(?:\/[^/?#]{3,}|\.?[^/?#.]\.?)*\/?)?(?:[?#]|$)/;
8
+ const CURRENT = './';
9
+ const PARENT = '../';
10
+ const QUERY = '?';
11
+ const FRAGMENT = '#';
12
+
13
+ export default class BaseIRI {
14
+ constructor(base) {
15
+ this.base = base;
16
+ this._baseLength = 0;
17
+ this._baseMatcher = null;
18
+ this._pathReplacements = new Array(base.length + 1);
19
+ }
20
+
21
+ static supports(base) {
22
+ return !BASE_UNSUPPORTED.test(base);
23
+ }
24
+
25
+ _getBaseMatcher() {
26
+ if (this._baseMatcher)
27
+ return this._baseMatcher;
28
+ if (!BaseIRI.supports(this.base))
29
+ return this._baseMatcher = /.^/;
30
+
31
+ // Extract the scheme
32
+ const scheme = /^[^:]*:\/*/.exec(this.base)[0];
33
+ const regexHead = ['^', escapeRegex(scheme)];
34
+ const regexTail = [];
35
+
36
+ // Generate a regex for every path segment
37
+ const segments = [], segmenter = /[^/?#]*([/?#])/y;
38
+ let segment, query = 0, fragment = 0, last = segmenter.lastIndex = scheme.length;
39
+ while (!query && !fragment && (segment = segmenter.exec(this.base))) {
40
+ // Truncate base resolution path at fragment start
41
+ if (segment[1] === FRAGMENT)
42
+ fragment = segmenter.lastIndex - 1;
43
+ else {
44
+ // Create regex that matches the segment
45
+ regexHead.push(escapeRegex(segment[0]), '(?:');
46
+ regexTail.push(')?');
47
+
48
+ // Create dedicated query string replacement
49
+ if (segment[1] !== QUERY)
50
+ segments.push(last = segmenter.lastIndex);
51
+ else {
52
+ query = last = segmenter.lastIndex;
53
+ fragment = this.base.indexOf(FRAGMENT, query);
54
+ this._pathReplacements[query] = QUERY;
55
+ }
56
+ }
57
+ }
58
+
59
+ // Precalculate parent path substitutions
60
+ for (let i = 0; i < segments.length; i++)
61
+ this._pathReplacements[segments[i]] = PARENT.repeat(segments.length - i - 1);
62
+ this._pathReplacements[segments[segments.length - 1]] = CURRENT;
63
+
64
+ // Add the remainder of the base IRI (without fragment) to the regex
65
+ this._baseLength = fragment > 0 ? fragment : this.base.length;
66
+ regexHead.push(
67
+ escapeRegex(this.base.substring(last, this._baseLength)),
68
+ query ? '(?:#|$)' : '(?:[?#]|$)',
69
+ );
70
+ return this._baseMatcher = new RegExp([...regexHead, ...regexTail].join(''));
71
+ }
72
+
73
+ toRelative(iri) {
74
+ // Unsupported or non-matching base IRI
75
+ const match = this._getBaseMatcher().exec(iri);
76
+ if (!match)
77
+ return iri;
78
+
79
+ // Exact base IRI match
80
+ const length = match[0].length;
81
+ if (length === this._baseLength && length === iri.length)
82
+ return '';
83
+
84
+ // Parent path match
85
+ const parentPath = this._pathReplacements[length];
86
+ if (parentPath) {
87
+ const suffix = iri.substring(length);
88
+ // Don't abbreviate unsupported path
89
+ if (parentPath !== QUERY && !SUFFIX_SUPPORTED.test(suffix))
90
+ return iri;
91
+ // Omit ./ with fragment or query string
92
+ if (parentPath === CURRENT && /^[^?#]/.test(suffix))
93
+ return suffix;
94
+ // Append suffix to relative parent path
95
+ return parentPath + suffix;
96
+ }
97
+
98
+ // Fragment or query string, so include delimiter
99
+ return iri.substring(length - 1);
100
+ }
101
+ }
package/src/IRIs.js CHANGED
@@ -28,5 +28,6 @@ export default {
28
28
  },
29
29
  log: {
30
30
  implies: `${SWAP}log#implies`,
31
+ isImpliedBy: `${SWAP}log#isImpliedBy`,
31
32
  },
32
33
  };
package/src/N3Lexer.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // **N3Lexer** tokenizes N3 documents.
2
2
  import { Buffer } from 'buffer';
3
- import queueMicrotask from 'queue-microtask';
4
3
  import namespaces from './IRIs';
5
4
 
6
5
  const { xsd } = namespaces;
@@ -56,6 +55,9 @@ export default class N3Lexer {
56
55
  this._endOfFile = /^(?:#[^\n\r]*)?$/;
57
56
  options = options || {};
58
57
 
58
+ // Whether the log:isImpliedBy predicate is supported
59
+ this._isImpliedBy = options.isImpliedBy;
60
+
59
61
  // In line mode (N-Triples or N-Quads), only simple features may be parsed
60
62
  if (this._lineMode = !!options.lineMode) {
61
63
  this._n3Mode = false;
@@ -157,8 +159,11 @@ export default class N3Lexer {
157
159
  else if (!this._lineMode && input.length > (inputFinished ? 1 : 2) && input[1] === '<')
158
160
  type = '<<', matchLength = 2;
159
161
  // Try to find a backwards implication arrow
160
- else if (this._n3Mode && input.length > 1 && input[1] === '=')
161
- type = 'inverse', matchLength = 2, value = '>';
162
+ else if (this._n3Mode && input.length > 1 && input[1] === '=') {
163
+ matchLength = 2;
164
+ if (this._isImpliedBy) type = 'abbreviation', value = '<';
165
+ else type = 'inverse', value = '>';
166
+ }
162
167
  break;
163
168
 
164
169
  case '>':