n3 1.24.2 → 1.25.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,134 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ class BaseIRI {
8
+ constructor(iri) {
9
+ if (iri.startsWith('file://')) {
10
+ // Base IRIs starting with file:// are not supported. Silently fail.
11
+ return;
12
+ }
13
+
14
+ // Generate regex for baseIRI with optional groups for segments
15
+ // Stage 0: find the first scheme delimiter -> stage 1
16
+ // Stage 1: find the next /, ?, or #. '/' -> new segment -> stage 1, '?' -> stage 2, '#' -> update end to position before hash -> stage 3, none -> stage 3
17
+ // Stage 2: find the next #. '#' -> update end to position before hash -> stage 3, none -> stage 3
18
+ // Stage 3: find the end of the string, add '$' to this last segment
19
+ this._baseSubstitutions = {};
20
+ let baseIRIRegex = '';
21
+ let segmentsCount = 0;
22
+ let stage = 0;
23
+ const slashPositions = [];
24
+ let i = 0;
25
+ let containsQuery = false;
26
+ // Stage 0
27
+ const match = /:\/{0,2}/.exec(iri);
28
+ if (match) {
29
+ baseIRIRegex += escapeRegex(iri.substring(0, match.index + match[0].length));
30
+ i = match.index + match[0].length;
31
+ stage = 1;
32
+ } else {
33
+ // Base IRI should contain a scheme followed by its delimiter (e.g., http://). Silently fail.
34
+ return;
35
+ }
36
+ if (/\/\.{0,2}\//.test(iri.substring(i))) {
37
+ // Base IRIs containing `//`, `/./`, or `/../` are not supported. Silently fail.
38
+ return;
39
+ }
40
+ let end = iri.length;
41
+ while (stage === 1 && i < end) {
42
+ // Stage 1
43
+ const match = /[/?#]/.exec(iri.substring(i));
44
+ if (match) {
45
+ if (match[0] === '#') {
46
+ // Stop at this hash.
47
+ end = i + match.index;
48
+ stage = 3;
49
+ } else {
50
+ baseIRIRegex += escapeRegex(iri.substring(i, i + match.index + 1));
51
+ baseIRIRegex += '(';
52
+ segmentsCount++;
53
+ if (match[0] === '/') {
54
+ slashPositions.push(i + match.index);
55
+ } else {
56
+ this._baseSubstitutions[i + match.index] = '?';
57
+ containsQuery = true;
58
+ stage = 2;
59
+ }
60
+ i += match.index + 1;
61
+ }
62
+ } else {
63
+ stage = 3;
64
+ }
65
+ }
66
+ if (stage === 2) {
67
+ // Stage 2
68
+ const match = /#/.exec(iri.substring(i));
69
+ if (match) {
70
+ // Stop at this hash.
71
+ end = i + match.index;
72
+ }
73
+ stage = 3;
74
+ }
75
+ if (stage === 3) {
76
+ // Stage 3
77
+ baseIRIRegex += escapeRegex(iri.substring(i, end));
78
+ if (containsQuery) {
79
+ baseIRIRegex += '(#|$)';
80
+ } else {
81
+ baseIRIRegex += '([?#]|$)';
82
+ }
83
+ i = end;
84
+ }
85
+
86
+ // Complete the optional groups for the segments
87
+ baseIRIRegex += ')?'.repeat(segmentsCount);
88
+
89
+ // Precalculate the rest of the substitutions
90
+ if (this._baseSubstitutions[end - 1] === undefined) {
91
+ this._baseSubstitutions[end - 1] = '';
92
+ }
93
+ for (let i = 0; i < slashPositions.length; i++) {
94
+ this._baseSubstitutions[slashPositions[i]] = '../'.repeat(slashPositions.length - i - 1);
95
+ }
96
+ this._baseSubstitutions[slashPositions[slashPositions.length - 1]] = './';
97
+
98
+ // Set the baseMatcher
99
+ this._baseMatcher = new RegExp(baseIRIRegex);
100
+ this._baseLength = end;
101
+ this.value = iri.substring(0, end);
102
+ }
103
+ toRelative(iri) {
104
+ if (iri.startsWith('file://')) {
105
+ return iri;
106
+ }
107
+ const delimiterMatch = /:\/{0,2}/.exec(iri);
108
+ if (!delimiterMatch || /\/\.{0,2}\//.test(iri.substring(delimiterMatch.index + delimiterMatch[0].length))) {
109
+ return iri;
110
+ }
111
+ const match = this._baseMatcher.exec(iri);
112
+ if (!match) {
113
+ return iri;
114
+ }
115
+ const length = match[0].length;
116
+ if (length === this._baseLength && length === iri.length) {
117
+ return '';
118
+ }
119
+ let substitution = this._baseSubstitutions[length - 1];
120
+ if (substitution !== undefined) {
121
+ const substr = iri.substring(length);
122
+ if (substitution === './' && substr && (!substr.startsWith('#') && !substr.startsWith('?') || length === this._baseLength)) {
123
+ substitution = '';
124
+ }
125
+ return substitution + substr;
126
+ }
127
+ // Matched the [?#], so make sure to add the delimiter
128
+ return iri.substring(length - 1);
129
+ }
130
+ }
131
+ exports.default = BaseIRI;
132
+ function escapeRegex(regex) {
133
+ return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
134
+ }
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.
@@ -475,7 +474,7 @@ class N3Lexer {
475
474
  if (typeof input === 'string') {
476
475
  this._input = this._readStartingBom(input);
477
476
  // If a callback was passed, asynchronously call it
478
- if (typeof callback === 'function') (0, _queueMicrotask.default)(() => this._tokenizeToEnd(callback, true));
477
+ if (typeof callback === 'function') queueMicrotask(() => this._tokenizeToEnd(callback, true));
479
478
  // If no callback was passed, tokenize synchronously and return
480
479
  else {
481
480
  const tokens = [];
package/lib/N3Writer.js CHANGED
@@ -7,6 +7,7 @@ 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
+ var _BaseIRI = _interopRequireDefault(require("./BaseIRI"));
10
11
  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
12
  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; }
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -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
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,6 +147,7 @@ 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
152
  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
153
  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; }
@@ -158,6 +165,7 @@ var _default = exports.default = {
158
165
  StreamWriter: _N3StreamWriter.default,
159
166
  Util,
160
167
  Reasoner: _N3Reasoner.default,
168
+ BaseIRI: _BaseIRI.default,
161
169
  DataFactory: _N3DataFactory.default,
162
170
  Term: _N3DataFactory.Term,
163
171
  NamedNode: _N3DataFactory.NamedNode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "1.24.2",
3
+ "version": "1.25.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": {
package/src/BaseIRI.js ADDED
@@ -0,0 +1,136 @@
1
+ export default class BaseIRI {
2
+ constructor(iri) {
3
+ if (iri.startsWith('file://')) {
4
+ // Base IRIs starting with file:// are not supported. Silently fail.
5
+ return;
6
+ }
7
+
8
+ // Generate regex for baseIRI with optional groups for segments
9
+ // Stage 0: find the first scheme delimiter -> stage 1
10
+ // Stage 1: find the next /, ?, or #. '/' -> new segment -> stage 1, '?' -> stage 2, '#' -> update end to position before hash -> stage 3, none -> stage 3
11
+ // Stage 2: find the next #. '#' -> update end to position before hash -> stage 3, none -> stage 3
12
+ // Stage 3: find the end of the string, add '$' to this last segment
13
+ this._baseSubstitutions = {};
14
+ let baseIRIRegex = '';
15
+ let segmentsCount = 0;
16
+ let stage = 0;
17
+ const slashPositions = [];
18
+ let i = 0;
19
+ let containsQuery = false;
20
+ // Stage 0
21
+ const match = /:\/{0,2}/.exec(iri);
22
+ if (match) {
23
+ baseIRIRegex += escapeRegex(iri.substring(0, match.index + match[0].length));
24
+ i = match.index + match[0].length;
25
+ stage = 1;
26
+ }
27
+ else {
28
+ // Base IRI should contain a scheme followed by its delimiter (e.g., http://). Silently fail.
29
+ return;
30
+ }
31
+
32
+ if (/\/\.{0,2}\//.test(iri.substring(i))) {
33
+ // Base IRIs containing `//`, `/./`, or `/../` are not supported. Silently fail.
34
+ return;
35
+ }
36
+
37
+ let end = iri.length;
38
+ while (stage === 1 && i < end) {
39
+ // Stage 1
40
+ const match = /[/?#]/.exec(iri.substring(i));
41
+ if (match) {
42
+ if (match[0] === '#') {
43
+ // Stop at this hash.
44
+ end = i + match.index;
45
+ stage = 3;
46
+ }
47
+ else {
48
+ baseIRIRegex += escapeRegex(iri.substring(i, i + match.index + 1));
49
+ baseIRIRegex += '(';
50
+ segmentsCount++;
51
+ if (match[0] === '/') {
52
+ slashPositions.push(i + match.index);
53
+ }
54
+ else {
55
+ this._baseSubstitutions[i + match.index] = '?';
56
+ containsQuery = true;
57
+ stage = 2;
58
+ }
59
+ i += match.index + 1;
60
+ }
61
+ }
62
+ else {
63
+ stage = 3;
64
+ }
65
+ }
66
+ if (stage === 2) {
67
+ // Stage 2
68
+ const match = /#/.exec(iri.substring(i));
69
+ if (match) {
70
+ // Stop at this hash.
71
+ end = i + match.index;
72
+ }
73
+ stage = 3;
74
+ }
75
+ if (stage === 3) {
76
+ // Stage 3
77
+ baseIRIRegex += escapeRegex(iri.substring(i, end));
78
+ if (containsQuery) {
79
+ baseIRIRegex += '(#|$)';
80
+ }
81
+ else {
82
+ baseIRIRegex += '([?#]|$)';
83
+ }
84
+ i = end;
85
+ }
86
+
87
+ // Complete the optional groups for the segments
88
+ baseIRIRegex += ')?'.repeat(segmentsCount);
89
+
90
+ // Precalculate the rest of the substitutions
91
+ if (this._baseSubstitutions[end - 1] === undefined) {
92
+ this._baseSubstitutions[end - 1] = '';
93
+ }
94
+ for (let i = 0; i < slashPositions.length; i++) {
95
+ this._baseSubstitutions[slashPositions[i]] = '../'.repeat(slashPositions.length - i - 1);
96
+ }
97
+ this._baseSubstitutions[slashPositions[slashPositions.length - 1]] = './';
98
+
99
+ // Set the baseMatcher
100
+ this._baseMatcher = new RegExp(baseIRIRegex);
101
+ this._baseLength = end;
102
+ this.value = iri.substring(0, end);
103
+ }
104
+
105
+ toRelative(iri) {
106
+ if (iri.startsWith('file://')) {
107
+ return iri;
108
+ }
109
+ const delimiterMatch = /:\/{0,2}/.exec(iri);
110
+ if (!delimiterMatch || /\/\.{0,2}\//.test(iri.substring(delimiterMatch.index + delimiterMatch[0].length))) {
111
+ return iri;
112
+ }
113
+ const match = this._baseMatcher.exec(iri);
114
+ if (!match) {
115
+ return iri;
116
+ }
117
+ const length = match[0].length;
118
+ if (length === this._baseLength && length === iri.length) {
119
+ return '';
120
+ }
121
+ let substitution = this._baseSubstitutions[length - 1];
122
+ if (substitution !== undefined) {
123
+ const substr = iri.substring(length);
124
+ if (substitution === './' && substr && ((!substr.startsWith('#') && !substr.startsWith('?')) || length === this._baseLength)) {
125
+ substitution = '';
126
+ }
127
+ return substitution + substr;
128
+ }
129
+ // Matched the [?#], so make sure to add the delimiter
130
+ return iri.substring(length - 1);
131
+ }
132
+ }
133
+
134
+ function escapeRegex(regex) {
135
+ return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
136
+ }
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;
package/src/N3Writer.js CHANGED
@@ -2,6 +2,7 @@
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';
5
6
 
6
7
  const DEFAULTGRAPH = N3DataFactory.defaultGraph();
7
8
 
@@ -58,9 +59,7 @@ export default class N3Writer {
58
59
  this._prefixIRIs = Object.create(null);
59
60
  options.prefixes && this.addPrefixes(options.prefixes);
60
61
  if (options.baseIRI) {
61
- this._baseMatcher = new RegExp(`^${escapeRegex(options.baseIRI)
62
- }${options.baseIRI.endsWith('/') ? '' : '[#?]'}`);
63
- this._baseLength = options.baseIRI.length;
62
+ this._baseIri = new BaseIRI(options.baseIRI);
64
63
  }
65
64
  }
66
65
  else {
@@ -153,8 +152,9 @@ export default class N3Writer {
153
152
  }
154
153
  let iri = entity.value;
155
154
  // Use relative IRIs if requested and possible
156
- if (this._baseMatcher && this._baseMatcher.test(iri))
157
- iri = iri.substr(this._baseLength);
155
+ if (this._baseIri) {
156
+ iri = this._baseIri.toRelative(iri);
157
+ }
158
158
  // Escape special characters
159
159
  if (escape.test(iri))
160
160
  iri = iri.replace(escapeAll, characterReplacer);
package/src/index.js CHANGED
@@ -7,6 +7,7 @@ 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';
10
11
 
11
12
  import {
12
13
  default as DataFactory,
@@ -36,6 +37,7 @@ export {
36
37
  StreamWriter,
37
38
  Util,
38
39
  Reasoner,
40
+ BaseIRI,
39
41
 
40
42
  DataFactory,
41
43
 
@@ -65,6 +67,7 @@ export default {
65
67
  StreamWriter,
66
68
  Util,
67
69
  Reasoner,
70
+ BaseIRI,
68
71
 
69
72
  DataFactory,
70
73