n3 2.0.0-beta.2 → 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/README.md +15 -12
- package/browser/n3.min.js +1 -1
- package/lib/BaseIRI.js +93 -0
- package/lib/IRIs.js +2 -1
- package/lib/N3Lexer.js +8 -3
- package/lib/N3Parser.js +9 -2
- package/lib/N3Store.js +24 -23
- package/lib/N3Util.js +6 -0
- package/lib/N3Writer.js +9 -10
- package/lib/Util.js +9 -0
- package/lib/index.js +9 -2
- package/package.json +4 -5
- package/src/BaseIRI.js +101 -0
- package/src/IRIs.js +1 -0
- package/src/N3Lexer.js +8 -3
- package/src/N3Parser.js +8 -1
- package/src/N3Store.js +22 -21
- package/src/N3Util.js +5 -0
- package/src/N3Writer.js +8 -11
- package/src/Util.js +3 -0
- package/src/index.js +3 -0
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
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] === '=')
|
|
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') (
|
|
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,7 +43,8 @@ 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;
|
|
@@ -300,6 +303,7 @@ class N3Parser {
|
|
|
300
303
|
default:
|
|
301
304
|
if ((this._predicate = this._readEntity(token)) === undefined) return;
|
|
302
305
|
}
|
|
306
|
+
this._validAnnotation = true;
|
|
303
307
|
// The next token must be an object
|
|
304
308
|
return this._readObject;
|
|
305
309
|
}
|
|
@@ -657,12 +661,14 @@ class N3Parser {
|
|
|
657
661
|
case '{|':
|
|
658
662
|
// Continue using the last triple as reified triple subject for the predicate-object pairs.
|
|
659
663
|
this._subject = this._readTripleTerm();
|
|
664
|
+
this._validAnnotation = false;
|
|
660
665
|
startingAnnotation = true;
|
|
661
666
|
next = this._readPredicate;
|
|
662
667
|
break;
|
|
663
668
|
// |} means that the current reified triple in annotation syntax is finalized.
|
|
664
669
|
case '|}':
|
|
665
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);
|
|
666
672
|
this._subject = null;
|
|
667
673
|
this._annotation = false;
|
|
668
674
|
next = this._readPunctuation;
|
|
@@ -1184,7 +1190,8 @@ function initDataFactory(parser, factory) {
|
|
|
1184
1190
|
parser.ABBREVIATIONS = {
|
|
1185
1191
|
'a': factory.namedNode(_IRIs.default.rdf.type),
|
|
1186
1192
|
'=': factory.namedNode(_IRIs.default.owl.sameAs),
|
|
1187
|
-
'>': factory.namedNode(_IRIs.default.log.implies)
|
|
1193
|
+
'>': factory.namedNode(_IRIs.default.log.implies),
|
|
1194
|
+
'<': factory.namedNode(_IRIs.default.log.isImpliedBy)
|
|
1188
1195
|
};
|
|
1189
1196
|
parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
|
|
1190
1197
|
}
|
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
|
|
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.
|
|
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 (
|
|
1088
|
-
if (
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
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
|
-
|
|
11
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
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
|
|
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
|
|
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": "^
|
|
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
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
|
-
|
|
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 '>':
|
package/src/N3Parser.js
CHANGED
|
@@ -27,12 +27,14 @@ 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;
|
|
30
32
|
// Disable relative IRIs in N-Triples or N-Quads mode
|
|
31
33
|
if (isLineMode)
|
|
32
34
|
this._resolveRelativeIRI = iri => { return null; };
|
|
33
35
|
this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' :
|
|
34
36
|
options.blankNodePrefix.replace(/^(?!_:)/, '_:');
|
|
35
|
-
this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 });
|
|
37
|
+
this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3, isImpliedBy: this._isImpliedBy });
|
|
36
38
|
// Disable explicit quantifiers by default
|
|
37
39
|
this._explicitQuantifiers = !!options.explicitQuantifiers;
|
|
38
40
|
// Disable parsing of unsupported versions by default
|
|
@@ -314,6 +316,7 @@ export default class N3Parser {
|
|
|
314
316
|
if ((this._predicate = this._readEntity(token)) === undefined)
|
|
315
317
|
return;
|
|
316
318
|
}
|
|
319
|
+
this._validAnnotation = true;
|
|
317
320
|
// The next token must be an object
|
|
318
321
|
return this._readObject;
|
|
319
322
|
}
|
|
@@ -705,6 +708,7 @@ export default class N3Parser {
|
|
|
705
708
|
case '{|':
|
|
706
709
|
// Continue using the last triple as reified triple subject for the predicate-object pairs.
|
|
707
710
|
this._subject = this._readTripleTerm();
|
|
711
|
+
this._validAnnotation = false;
|
|
708
712
|
startingAnnotation = true;
|
|
709
713
|
next = this._readPredicate;
|
|
710
714
|
break;
|
|
@@ -712,6 +716,8 @@ export default class N3Parser {
|
|
|
712
716
|
case '|}':
|
|
713
717
|
if (!this._annotation)
|
|
714
718
|
return this._error('Unexpected annotation syntax closing', token);
|
|
719
|
+
if (!this._validAnnotation)
|
|
720
|
+
return this._error('Annotation block can not be empty', token);
|
|
715
721
|
this._subject = null;
|
|
716
722
|
this._annotation = false;
|
|
717
723
|
next = this._readPunctuation;
|
|
@@ -1270,6 +1276,7 @@ function initDataFactory(parser, factory) {
|
|
|
1270
1276
|
'a': factory.namedNode(namespaces.rdf.type),
|
|
1271
1277
|
'=': factory.namedNode(namespaces.owl.sameAs),
|
|
1272
1278
|
'>': factory.namedNode(namespaces.log.implies),
|
|
1279
|
+
'<': factory.namedNode(namespaces.log.isImpliedBy),
|
|
1273
1280
|
};
|
|
1274
1281
|
parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
|
|
1275
1282
|
}
|