n3 2.13.0 → 2.13.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/lib/N3Lexer.js CHANGED
@@ -136,7 +136,7 @@ class N3Lexer {
136
136
  if (!(key in lineModeRegExps) && this[key] instanceof RegExp) this[key] = invalidRegExp;
137
137
  }
138
138
  // The only keyword in N-Triples and N-Quads is VERSION, which is case-sensitive
139
- this._keyword = /VERSION(?=[\s#<])/y;
139
+ this._keyword = /VERSION(?=[\s#<"])/y;
140
140
  }
141
141
  // When not in line mode, enable N3 functionality by default
142
142
  else {
package/lib/N3Parser.js CHANGED
@@ -11,6 +11,10 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
11
11
  // **N3Parser** parses N3 documents.
12
12
 
13
13
  let blankNodePrefix = 0;
14
+ // Detects `.` and `..` path segments in an IRI
15
+ const dotSegments = /(^|\/)\.\.?($|[/#?])/;
16
+ // Detects `.` and `..` segments in the path of an IRI, ignoring its query and fragment
17
+ const pathDotSegments = /^[^?#]*(?:^|\/)\.\.?(?:$|[/#?])/;
14
18
 
15
19
  // ## Constructor
16
20
  class N3Parser {
@@ -91,6 +95,7 @@ class N3Parser {
91
95
  if (!baseIRI) {
92
96
  this._base = '';
93
97
  this._basePath = '';
98
+ this._basePathHasDotSegments = false;
94
99
  } else {
95
100
  // Remove fragment if present
96
101
  const fragmentPos = baseIRI.indexOf('#');
@@ -107,6 +112,8 @@ class N3Parser {
107
112
  // If the base has an authority but an empty path,
108
113
  // relative IRIs merge under the path '/' (RFC 3986 §5.2.3)
109
114
  if (baseIRI[2] !== undefined && (base.length === this._baseRoot.length || base[this._baseRoot.length] === '?')) this._basePath = `${this._baseRoot}/`;
115
+ // Check once whether resolving against the base path needs to remove dot segments
116
+ this._basePathHasDotSegments = dotSegments.test(this._basePath);
110
117
  }
111
118
  }
112
119
 
@@ -153,7 +160,7 @@ class N3Parser {
153
160
  // Prefix and base declarations are scoped to their formula,
154
161
  // so record prefix changes to undo them when the formula ends
155
162
  if (type === 'formula') {
156
- context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme];
163
+ context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme, this._basePathHasDotSegments];
157
164
  this._prefixChanges = [];
158
165
  }
159
166
  this._contextStack.push(context);
@@ -193,7 +200,7 @@ class N3Parser {
193
200
  if (this._n3Mode) {
194
201
  this._inversePredicate = context.inverse;
195
202
  this._expectOf = context.expectOf;
196
- if (type === 'formula') [this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
203
+ if (type === 'formula') [this._base, this._basePath, this._baseRoot, this._baseScheme, this._basePathHasDotSegments] = context.base;
197
204
  if (this._prefixChanges !== context.prefixChanges) {
198
205
  undoChanges(this._prefixes, this._prefixChanges);
199
206
  this._prefixChanges = context.prefixChanges;
@@ -1455,14 +1462,17 @@ class N3Parser {
1455
1462
  // Resolve all other IRIs at the base IRI's path
1456
1463
  default:
1457
1464
  // Relative IRIs cannot contain a colon in the first path segment
1458
- return /^[^/:]*:/.test(iri) ? null : this._removeDotSegments(this._basePath + iri);
1465
+ if (/^[^/:]*:/.test(iri)) return null;
1466
+ // Only scan the joined IRI for dot segments if either part can contain them,
1467
+ // as the base path can be long and the joined IRI would need to be copied
1468
+ return this._basePathHasDotSegments || pathDotSegments.test(iri) ? this._removeDotSegments(this._basePath + iri) : this._basePath + iri;
1459
1469
  }
1460
1470
  }
1461
1471
 
1462
1472
  // ### `_removeDotSegments` resolves './' and '../' path segments in an IRI as per RFC3986
1463
1473
  _removeDotSegments(iri) {
1464
1474
  // Don't modify the IRI if it does not contain any dot segments
1465
- if (!/(^|\/)\.\.?($|[/#?])/.test(iri)) return iri;
1475
+ if (!dotSegments.test(iri)) return iri;
1466
1476
 
1467
1477
  // Start with an imaginary slash before the IRI in order to resolve trailing './' and '../'
1468
1478
  const length = iri.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.13.0",
3
+ "version": "2.13.2",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
package/src/N3Lexer.js CHANGED
@@ -102,7 +102,7 @@ export default class N3Lexer {
102
102
  this[key] = invalidRegExp;
103
103
  }
104
104
  // The only keyword in N-Triples and N-Quads is VERSION, which is case-sensitive
105
- this._keyword = /VERSION(?=[\s#<])/y;
105
+ this._keyword = /VERSION(?=[\s#<"])/y;
106
106
  }
107
107
  // When not in line mode, enable N3 functionality by default
108
108
  else {
package/src/N3Parser.js CHANGED
@@ -4,6 +4,10 @@ import N3DataFactory from './N3DataFactory';
4
4
  import namespaces from './IRIs';
5
5
 
6
6
  let blankNodePrefix = 0;
7
+ // Detects `.` and `..` path segments in an IRI
8
+ const dotSegments = /(^|\/)\.\.?($|[/#?])/;
9
+ // Detects `.` and `..` segments in the path of an IRI, ignoring its query and fragment
10
+ const pathDotSegments = /^[^?#]*(?:^|\/)\.\.?(?:$|[/#?])/;
7
11
 
8
12
  // ## Constructor
9
13
  export default class N3Parser {
@@ -83,6 +87,7 @@ export default class N3Parser {
83
87
  if (!baseIRI) {
84
88
  this._base = '';
85
89
  this._basePath = '';
90
+ this._basePathHasDotSegments = false;
86
91
  }
87
92
  else {
88
93
  // Remove fragment if present
@@ -103,6 +108,8 @@ export default class N3Parser {
103
108
  // relative IRIs merge under the path '/' (RFC 3986 §5.2.3)
104
109
  if (baseIRI[2] !== undefined && (base.length === this._baseRoot.length || base[this._baseRoot.length] === '?'))
105
110
  this._basePath = `${this._baseRoot}/`;
111
+ // Check once whether resolving against the base path needs to remove dot segments
112
+ this._basePathHasDotSegments = dotSegments.test(this._basePath);
106
113
  }
107
114
  }
108
115
 
@@ -140,7 +147,8 @@ export default class N3Parser {
140
147
  // Prefix and base declarations are scoped to their formula,
141
148
  // so record prefix changes to undo them when the formula ends
142
149
  if (type === 'formula') {
143
- context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme];
150
+ context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme,
151
+ this._basePathHasDotSegments];
144
152
  this._prefixChanges = [];
145
153
  }
146
154
  this._contextStack.push(context);
@@ -182,7 +190,8 @@ export default class N3Parser {
182
190
  this._inversePredicate = context.inverse;
183
191
  this._expectOf = context.expectOf;
184
192
  if (type === 'formula')
185
- [this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
193
+ [this._base, this._basePath, this._baseRoot, this._baseScheme,
194
+ this._basePathHasDotSegments] = context.base;
186
195
  if (this._prefixChanges !== context.prefixChanges) {
187
196
  undoChanges(this._prefixes, this._prefixChanges);
188
197
  this._prefixChanges = context.prefixChanges;
@@ -1576,14 +1585,19 @@ export default class N3Parser {
1576
1585
  // Resolve all other IRIs at the base IRI's path
1577
1586
  default:
1578
1587
  // Relative IRIs cannot contain a colon in the first path segment
1579
- return (/^[^/:]*:/.test(iri)) ? null : this._removeDotSegments(this._basePath + iri);
1588
+ if (/^[^/:]*:/.test(iri))
1589
+ return null;
1590
+ // Only scan the joined IRI for dot segments if either part can contain them,
1591
+ // as the base path can be long and the joined IRI would need to be copied
1592
+ return this._basePathHasDotSegments || pathDotSegments.test(iri) ?
1593
+ this._removeDotSegments(this._basePath + iri) : this._basePath + iri;
1580
1594
  }
1581
1595
  }
1582
1596
 
1583
1597
  // ### `_removeDotSegments` resolves './' and '../' path segments in an IRI as per RFC3986
1584
1598
  _removeDotSegments(iri) {
1585
1599
  // Don't modify the IRI if it does not contain any dot segments
1586
- if (!/(^|\/)\.\.?($|[/#?])/.test(iri))
1600
+ if (!dotSegments.test(iri))
1587
1601
  return iri;
1588
1602
 
1589
1603
  // Start with an imaginary slash before the IRI in order to resolve trailing './' and '../'