n3 2.11.6 → 2.11.8
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/browser/n3.esm.min.js +12 -12
- package/browser/n3.min.js +12 -12
- package/lib/N3Lexer.js +25 -15
- package/lib/N3Writer.js +16 -10
- package/package.json +1 -1
- package/src/N3Lexer.js +27 -19
- package/src/N3Writer.js +16 -10
package/lib/N3Lexer.js
CHANGED
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var _buffer = require("buffer");
|
|
8
7
|
var _IRIs = _interopRequireDefault(require("./IRIs"));
|
|
9
8
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
9
|
// **N3Lexer** tokenizes N3 documents.
|
|
@@ -94,6 +93,9 @@ function isSeparatorCode(code) {
|
|
|
94
93
|
return code === SPACE || code === TAB || code === LF || code === CR || code === HASH;
|
|
95
94
|
}
|
|
96
95
|
|
|
96
|
+
// Unfinished input in a stream up to this length is tokenized again with every chunk
|
|
97
|
+
const MIN_RESCAN_LENGTH = 1024;
|
|
98
|
+
|
|
97
99
|
// ## Constructor
|
|
98
100
|
class N3Lexer {
|
|
99
101
|
constructor(options) {
|
|
@@ -721,31 +723,39 @@ class N3Lexer {
|
|
|
721
723
|
}
|
|
722
724
|
// Otherwise, the input must be a stream
|
|
723
725
|
else {
|
|
724
|
-
|
|
726
|
+
let decoder,
|
|
727
|
+
retryLength = 0;
|
|
725
728
|
if (typeof input.setEncoding === 'function') input.setEncoding('utf8');
|
|
726
729
|
// Adds the data chunk to the buffer and parses as far as possible
|
|
727
730
|
input.on('data', data => {
|
|
728
731
|
if (this._tokenization === tokenization && this._input !== null && data.length !== 0) {
|
|
729
|
-
//
|
|
730
|
-
if (
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
732
|
+
// Decode bytes, keeping an incomplete trailing character for the next chunk
|
|
733
|
+
if (typeof data !== 'string') {
|
|
734
|
+
decoder = decoder || new TextDecoder('utf-8', {
|
|
735
|
+
ignoreBOM: true
|
|
736
|
+
});
|
|
737
|
+
if (!(data = decoder.decode(data, {
|
|
738
|
+
stream: true
|
|
739
|
+
}))) return;
|
|
737
740
|
}
|
|
738
|
-
//
|
|
739
|
-
else
|
|
740
|
-
|
|
741
|
-
|
|
741
|
+
// Only read a BOM at the start
|
|
742
|
+
if (typeof this._input === 'undefined') this._input = this._readStartingBom(data);else this._input += data;
|
|
743
|
+
// Tokenize as far as possible. When a previous attempt left a long unfinished token,
|
|
744
|
+
// wait until the buffered input has doubled, so the token is not rescanned for every chunk.
|
|
745
|
+
if (this._input.length >= retryLength) {
|
|
742
746
|
this._tokenizeToEnd(callback, false);
|
|
747
|
+
retryLength = this._input !== null && this._input.length > MIN_RESCAN_LENGTH ? 2 * this._input.length : 0;
|
|
743
748
|
}
|
|
744
749
|
}
|
|
745
750
|
});
|
|
746
751
|
// Parses until the end
|
|
747
752
|
input.on('end', () => {
|
|
748
|
-
if (this._tokenization === tokenization &&
|
|
753
|
+
if (this._tokenization === tokenization && this._input !== null) {
|
|
754
|
+
// Decode any incomplete character left at the end
|
|
755
|
+
const rest = decoder ? decoder.decode() : '';
|
|
756
|
+
if (rest) this._input = typeof this._input === 'string' ? this._input + rest : rest;
|
|
757
|
+
if (typeof this._input === 'string') this._tokenizeToEnd(callback, true);
|
|
758
|
+
}
|
|
749
759
|
});
|
|
750
760
|
input.on('error', error => {
|
|
751
761
|
if (this._tokenization === tokenization) callback(error);
|
package/lib/N3Writer.js
CHANGED
|
@@ -188,7 +188,7 @@ class N3Writer {
|
|
|
188
188
|
// Escape special characters
|
|
189
189
|
if (this._escape.test(iri)) iri = iri.replace(this._escapeAll, this._characterReplacer);
|
|
190
190
|
// Try to represent the IRI as prefixed name, unless no prefixes were added
|
|
191
|
-
const prefixMatch = this._hasPrefixes ? this._prefixRegex.exec(iri) : null;
|
|
191
|
+
const prefixMatch = this._hasPrefixes ? (this._prefixRegex || this._createPrefixRegex()).exec(iri) : null;
|
|
192
192
|
return !prefixMatch ? `<${iri}>` : !prefixMatch[1] ? iri : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2];
|
|
193
193
|
}
|
|
194
194
|
|
|
@@ -319,22 +319,28 @@ class N3Writer {
|
|
|
319
319
|
this._prefixPatterns[iri] = [(0, _Util.escapeRegex)(iri), (0, _Util.escapeRegex)(prefix)];
|
|
320
320
|
this._write(`@prefix ${prefix} <${iri}>.\n`);
|
|
321
321
|
}
|
|
322
|
-
// Recreate the prefix matcher
|
|
322
|
+
// Recreate the prefix matcher when it is next needed, so that adding
|
|
323
|
+
// prefixes one by one does not rebuild it for every prefix
|
|
323
324
|
if (hasPrefixes) {
|
|
324
325
|
this._hasPrefixes = true;
|
|
325
|
-
|
|
326
|
-
prefixList = '';
|
|
327
|
-
for (const prefixIRI in this._prefixPatterns) {
|
|
328
|
-
const [IRIpattern, prefixPattern] = this._prefixPatterns[prefixIRI];
|
|
329
|
-
IRIlist += IRIlist ? `|${IRIpattern}` : IRIpattern;
|
|
330
|
-
prefixList += prefixList ? `|${prefixPattern}` : prefixPattern;
|
|
331
|
-
}
|
|
332
|
-
this._prefixRegex = new RegExp(`^(?:${prefixList})[^/]*$|` + `^(${IRIlist})([_a-zA-Z0-9](?:\\.?[\\-_a-zA-Z0-9])*)$`);
|
|
326
|
+
this._prefixRegex = null;
|
|
333
327
|
}
|
|
334
328
|
// End a prefix block with a newline
|
|
335
329
|
this._write(hasPrefixes ? '\n' : '', done);
|
|
336
330
|
}
|
|
337
331
|
|
|
332
|
+
// ### `_createPrefixRegex` creates the matcher for the current prefixes
|
|
333
|
+
_createPrefixRegex() {
|
|
334
|
+
let IRIlist = '',
|
|
335
|
+
prefixList = '';
|
|
336
|
+
for (const prefixIRI in this._prefixPatterns) {
|
|
337
|
+
const [IRIpattern, prefixPattern] = this._prefixPatterns[prefixIRI];
|
|
338
|
+
IRIlist += IRIlist ? `|${IRIpattern}` : IRIpattern;
|
|
339
|
+
prefixList += prefixList ? `|${prefixPattern}` : prefixPattern;
|
|
340
|
+
}
|
|
341
|
+
return this._prefixRegex = new RegExp(`^(?:${prefixList})[^/]*$|` + `^(${IRIlist})([_a-zA-Z0-9](?:\\.?[\\-_a-zA-Z0-9])*)$`);
|
|
342
|
+
}
|
|
343
|
+
|
|
338
344
|
// ### `blank` creates a blank node with the given content
|
|
339
345
|
blank(predicate, object) {
|
|
340
346
|
let children = predicate,
|
package/package.json
CHANGED
package/src/N3Lexer.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// **N3Lexer** tokenizes N3 documents.
|
|
2
|
-
import { Buffer } from 'buffer';
|
|
3
2
|
import namespaces from './IRIs';
|
|
4
3
|
|
|
5
4
|
const { xsd } = namespaces;
|
|
@@ -59,6 +58,9 @@ function isSeparatorCode(code) {
|
|
|
59
58
|
return code === SPACE || code === TAB || code === LF || code === CR || code === HASH;
|
|
60
59
|
}
|
|
61
60
|
|
|
61
|
+
// Unfinished input in a stream up to this length is tokenized again with every chunk
|
|
62
|
+
const MIN_RESCAN_LENGTH = 1024;
|
|
63
|
+
|
|
62
64
|
// ## Constructor
|
|
63
65
|
export default class N3Lexer {
|
|
64
66
|
constructor(options) {
|
|
@@ -747,36 +749,42 @@ export default class N3Lexer {
|
|
|
747
749
|
}
|
|
748
750
|
// Otherwise, the input must be a stream
|
|
749
751
|
else {
|
|
750
|
-
|
|
752
|
+
let decoder, retryLength = 0;
|
|
751
753
|
if (typeof input.setEncoding === 'function')
|
|
752
754
|
input.setEncoding('utf8');
|
|
753
755
|
// Adds the data chunk to the buffer and parses as far as possible
|
|
754
756
|
input.on('data', data => {
|
|
755
757
|
if (this._tokenization === tokenization && this._input !== null && data.length !== 0) {
|
|
756
|
-
//
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
// Hold if the buffer ends in an incomplete unicode sequence
|
|
762
|
-
if (data[data.length - 1] & 0x80) {
|
|
763
|
-
this._pendingBuffer = data;
|
|
758
|
+
// Decode bytes, keeping an incomplete trailing character for the next chunk
|
|
759
|
+
if (typeof data !== 'string') {
|
|
760
|
+
decoder = decoder || new TextDecoder('utf-8', { ignoreBOM: true });
|
|
761
|
+
if (!(data = decoder.decode(data, { stream: true })))
|
|
762
|
+
return;
|
|
764
763
|
}
|
|
765
|
-
//
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
764
|
+
// Only read a BOM at the start
|
|
765
|
+
if (typeof this._input === 'undefined')
|
|
766
|
+
this._input = this._readStartingBom(data);
|
|
767
|
+
else
|
|
768
|
+
this._input += data;
|
|
769
|
+
// Tokenize as far as possible. When a previous attempt left a long unfinished token,
|
|
770
|
+
// wait until the buffered input has doubled, so the token is not rescanned for every chunk.
|
|
771
|
+
if (this._input.length >= retryLength) {
|
|
772
772
|
this._tokenizeToEnd(callback, false);
|
|
773
|
+
retryLength = this._input !== null && this._input.length > MIN_RESCAN_LENGTH ?
|
|
774
|
+
2 * this._input.length : 0;
|
|
773
775
|
}
|
|
774
776
|
}
|
|
775
777
|
});
|
|
776
778
|
// Parses until the end
|
|
777
779
|
input.on('end', () => {
|
|
778
|
-
if (this._tokenization === tokenization &&
|
|
779
|
-
|
|
780
|
+
if (this._tokenization === tokenization && this._input !== null) {
|
|
781
|
+
// Decode any incomplete character left at the end
|
|
782
|
+
const rest = decoder ? decoder.decode() : '';
|
|
783
|
+
if (rest)
|
|
784
|
+
this._input = typeof this._input === 'string' ? this._input + rest : rest;
|
|
785
|
+
if (typeof this._input === 'string')
|
|
786
|
+
this._tokenizeToEnd(callback, true);
|
|
787
|
+
}
|
|
780
788
|
});
|
|
781
789
|
input.on('error', error => {
|
|
782
790
|
if (this._tokenization === tokenization)
|
package/src/N3Writer.js
CHANGED
|
@@ -189,7 +189,7 @@ export default class N3Writer {
|
|
|
189
189
|
if (this._escape.test(iri))
|
|
190
190
|
iri = iri.replace(this._escapeAll, this._characterReplacer);
|
|
191
191
|
// Try to represent the IRI as prefixed name, unless no prefixes were added
|
|
192
|
-
const prefixMatch = this._hasPrefixes ? this._prefixRegex.exec(iri) : null;
|
|
192
|
+
const prefixMatch = this._hasPrefixes ? (this._prefixRegex || this._createPrefixRegex()).exec(iri) : null;
|
|
193
193
|
return !prefixMatch ? `<${iri}>` :
|
|
194
194
|
(!prefixMatch[1] ? iri : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]);
|
|
195
195
|
}
|
|
@@ -333,22 +333,28 @@ export default class N3Writer {
|
|
|
333
333
|
this._prefixPatterns[iri] = [escapeRegex(iri), escapeRegex(prefix)];
|
|
334
334
|
this._write(`@prefix ${prefix} <${iri}>.\n`);
|
|
335
335
|
}
|
|
336
|
-
// Recreate the prefix matcher
|
|
336
|
+
// Recreate the prefix matcher when it is next needed, so that adding
|
|
337
|
+
// prefixes one by one does not rebuild it for every prefix
|
|
337
338
|
if (hasPrefixes) {
|
|
338
339
|
this._hasPrefixes = true;
|
|
339
|
-
|
|
340
|
-
for (const prefixIRI in this._prefixPatterns) {
|
|
341
|
-
const [IRIpattern, prefixPattern] = this._prefixPatterns[prefixIRI];
|
|
342
|
-
IRIlist += IRIlist ? `|${IRIpattern}` : IRIpattern;
|
|
343
|
-
prefixList += prefixList ? `|${prefixPattern}` : prefixPattern;
|
|
344
|
-
}
|
|
345
|
-
this._prefixRegex = new RegExp(`^(?:${prefixList})[^/]*$|` +
|
|
346
|
-
`^(${IRIlist})([_a-zA-Z0-9](?:\\.?[\\-_a-zA-Z0-9])*)$`);
|
|
340
|
+
this._prefixRegex = null;
|
|
347
341
|
}
|
|
348
342
|
// End a prefix block with a newline
|
|
349
343
|
this._write(hasPrefixes ? '\n' : '', done);
|
|
350
344
|
}
|
|
351
345
|
|
|
346
|
+
// ### `_createPrefixRegex` creates the matcher for the current prefixes
|
|
347
|
+
_createPrefixRegex() {
|
|
348
|
+
let IRIlist = '', prefixList = '';
|
|
349
|
+
for (const prefixIRI in this._prefixPatterns) {
|
|
350
|
+
const [IRIpattern, prefixPattern] = this._prefixPatterns[prefixIRI];
|
|
351
|
+
IRIlist += IRIlist ? `|${IRIpattern}` : IRIpattern;
|
|
352
|
+
prefixList += prefixList ? `|${prefixPattern}` : prefixPattern;
|
|
353
|
+
}
|
|
354
|
+
return this._prefixRegex = new RegExp(`^(?:${prefixList})[^/]*$|` +
|
|
355
|
+
`^(${IRIlist})([_a-zA-Z0-9](?:\\.?[\\-_a-zA-Z0-9])*)$`);
|
|
356
|
+
}
|
|
357
|
+
|
|
352
358
|
// ### `blank` creates a blank node with the given content
|
|
353
359
|
blank(predicate, object) {
|
|
354
360
|
let children = predicate, child, length;
|