Comparing version
@@ -318,37 +318,31 @@ // **N3Lexer** tokenizes N3 documents. | ||
this._input = input; | ||
immediately(function () { self._tokenizeToEnd(callback, true); }); | ||
// If a callback was passed, asynchronously call it | ||
if (typeof callback === 'function') | ||
immediately(function () { self._tokenizeToEnd(callback, true); }); | ||
// If no callback was passed, tokenize synchronously and return | ||
else { | ||
var tokens = [], error; | ||
this._tokenizeToEnd(function (e, t) { e ? (error = e) : tokens.push(t); }, true); | ||
if (error) throw error; | ||
return tokens; | ||
} | ||
} | ||
// Otherwise, the input will be streamed. | ||
// Otherwise, the input must be a stream. | ||
else { | ||
this._input = ''; | ||
// If no input was given, it will be streamed through `addChunk` and ended with `end` | ||
if (!input || typeof input === 'function') { | ||
this.addChunk = addChunk; | ||
this.end = end; | ||
if (!callback) | ||
callback = input; | ||
} | ||
// Otherwise, the input itself must be a stream | ||
else { | ||
if (typeof input.setEncoding === 'function') | ||
input.setEncoding('utf8'); | ||
input.on('data', addChunk); | ||
input.on('end', end); | ||
} | ||
if (typeof input.setEncoding === 'function') | ||
input.setEncoding('utf8'); | ||
// Adds the data chunk to the buffer and parses as far as possible | ||
input.on('data', function (data) { | ||
if (self._input !== null) { | ||
self._input += data; | ||
self._tokenizeToEnd(callback, false); | ||
} | ||
}); | ||
// Parses until the end | ||
input.on('end', function () { | ||
if (self._input !== null) | ||
self._tokenizeToEnd(callback, true); | ||
}); | ||
} | ||
// Adds the data chunk to the buffer and parses as far as possible | ||
function addChunk(data) { | ||
if (self._input !== null) { | ||
self._input += data; | ||
self._tokenizeToEnd(callback, false); | ||
} | ||
} | ||
// Parses until the end | ||
function end() { | ||
if (self._input !== null) | ||
self._tokenizeToEnd(callback, true); | ||
} | ||
}, | ||
@@ -355,0 +349,0 @@ }; |
@@ -663,2 +663,3 @@ // **N3Parser** parses N3 documents. | ||
parse: function (input, tripleCallback, prefixCallback) { | ||
var self = this; | ||
// The read callback is the next function to be executed when a token arrives. | ||
@@ -670,24 +671,22 @@ // We start reading in the top context. | ||
// If the input argument is not given, shift parameters | ||
if (typeof input === 'function') | ||
prefixCallback = tripleCallback, tripleCallback = input, input = null; | ||
// Parse synchronously if no callbacks are given. | ||
if (!tripleCallback && !prefixCallback) { | ||
var triples = [], error; | ||
this._callback = function (e, t) { e ? (error = e) : t && triples.push(t); }; | ||
this._lexer.tokenize(input).every(function (token) { | ||
return self._readCallback = self._readCallback(token); | ||
}); | ||
if (error) throw error; | ||
return triples; | ||
} | ||
// Set the triple and prefix callbacks. | ||
// Parse asynchronously otherwise, executing the read callback when a token arrives. | ||
this._callback = tripleCallback || noop; | ||
this._prefixCallback = prefixCallback || noop; | ||
// Execute the read callback when a token arrives. | ||
var self = this; | ||
this._lexer.tokenize(input, function (error, token) { | ||
if (error !== null) | ||
self._callback(error), self._callback = noop; | ||
else if (self._readCallback !== undefined) | ||
else if (self._readCallback) | ||
self._readCallback = self._readCallback(token); | ||
}); | ||
// If no input was given, it can be added with `addChunk` and ended with `end` | ||
if (!input) { | ||
this.addChunk = this._lexer.addChunk; | ||
this.end = this._lexer.end; | ||
} | ||
}, | ||
@@ -694,0 +693,0 @@ }; |
@@ -369,2 +369,3 @@ // **N3Store** objects store N3 triples by graph in memory. | ||
this._ids[name] = ++this._id; | ||
this._entities[this._id] = name; | ||
return name; | ||
@@ -371,0 +372,0 @@ }, |
@@ -16,15 +16,14 @@ // **N3StreamParser** parses an N3 stream into a triple stream | ||
// Set up parser | ||
var self = this, parser = new N3Parser(options); | ||
var self = this, parser = new N3Parser(options), onData, onEnd; | ||
parser.parse( | ||
// Pass dummy stream to obtain `data` and `end` callbacks | ||
{ on: function (event, cb) { event === 'data' ? (onData = cb) : (onEnd = cb); } }, | ||
// Handle triples by pushing them down the pipeline | ||
function (error, triple) { | ||
triple && self.push(triple) || | ||
error && self.emit('error', error); | ||
}, | ||
function (error, t) { error && self.emit('error', error) || t && self.push(t); }, | ||
// Emit prefixes through the `prefix` event | ||
this.emit.bind(this, 'prefix')); | ||
function (prefix, uri) { self.emit('prefix', prefix, uri); }); | ||
// Implement Transform methods on top of parser | ||
this._transform = function (chunk, encoding, done) { parser.addChunk(chunk); done(); }; | ||
this._flush = function (done) { parser.end(); done(); }; | ||
// Implement Transform methods through parser callbacks | ||
this._transform = function (chunk, encoding, done) { onData(chunk); done(); }; | ||
this._flush = function (done) { onEnd(); done(); }; | ||
} | ||
@@ -31,0 +30,0 @@ util.inherits(N3StreamParser, Transform); |
{ | ||
"name": "n3", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.", | ||
@@ -5,0 +5,0 @@ "author": "Ruben Verborgh <ruben.verborgh@gmail.com>", |
@@ -128,2 +128,4 @@ # Lightning fast, asynchronous, streaming RDF for JavaScript | ||
Pass a second callback to `parse` to retrieve prefixes as they are read. | ||
<br> | ||
If no callbacks are provided, parsing happens synchronously. | ||
@@ -139,22 +141,2 @@ By default, `N3.Parser` parses a permissive superset of Turtle, TriG, N-Triples and N-Quads. | ||
### From RDF chunks to triples | ||
`N3.Parser` can also parse triples from RDF documents arriving in chunks, | ||
for instance, when being downloaded or read from disk. | ||
Use `addChunk` to add a piece of data, and `end` to signal the end. | ||
``` js | ||
var parser = N3.Parser(), triples = []; | ||
parser.parse(function (error, triple, prefixes) { triple && triples.push(triple); }); | ||
parser.addChunk('@prefix c: <http://example.org/cartoons#>.\n'); | ||
parser.addChunk('c:Tom a '); | ||
parser.addChunk('c:Cat. c:Jerry a'); | ||
console.log(triples); // First triple | ||
parser.addChunk(' c:Mouse.'); | ||
parser.end(); | ||
console.log(triples); // Both triples | ||
``` | ||
### From an RDF stream to triples | ||
@@ -161,0 +143,0 @@ |
var N3Lexer = require('../N3').Lexer; | ||
var chai = require('chai'), | ||
events = require('events'); | ||
EventEmitter = require('events'); | ||
var expect = chai.expect; | ||
@@ -75,4 +75,4 @@ chai.should(); | ||
// Try parsing | ||
var lexer = new N3Lexer(); | ||
lexer.tokenize(function (error, token) { | ||
var stream = new EventEmitter(), lexer = new N3Lexer(); | ||
lexer.tokenize(stream, function (error, token) { | ||
error.should.be.an.instanceof(Error); | ||
@@ -82,3 +82,3 @@ error.message.should.equal('Syntax error: unexpected "<\\u1234>" on line 1.'); | ||
}); | ||
lexer.addChunk('<\\u1234>'); | ||
stream.emit('data', '<\\u1234>'); | ||
// Restore global isNaN | ||
@@ -93,4 +93,4 @@ global.isNaN = isNaN; | ||
// Try parsing | ||
var lexer = new N3Lexer(); | ||
lexer.tokenize(function (error, token) { | ||
var stream = new EventEmitter(), lexer = new N3Lexer(); | ||
lexer.tokenize(stream, function (error, token) { | ||
error.should.be.an.instanceof(Error); | ||
@@ -100,3 +100,3 @@ error.message.should.equal('Syntax error: unexpected "<\\U12345678>" on line 1.'); | ||
}); | ||
lexer.addChunk('<\\U12345678>'); | ||
stream.emit('data', '<\\U12345678>'); | ||
// Restore global isNaN | ||
@@ -652,22 +652,9 @@ global.isNaN = isNaN; | ||
describe('using the addChunk/end interface', function () { | ||
var tokens = [], lexer = new N3Lexer(); | ||
lexer.tokenize(function (error, token) { !error && tokens.push(token); }); | ||
lexer.addChunk('<a> '); | ||
lexer.addChunk('<b> '); | ||
lexer.addChunk('<c>.'); | ||
lexer.end(); | ||
it('parses all chunks', function () { | ||
tokens.should.have.length(5); | ||
}); | ||
}); | ||
describe('passing data after the stream has been finished', function () { | ||
var tokens = [], lexer = new N3Lexer(); | ||
lexer.tokenize(function (error, token) { !error && tokens.push(token); }); | ||
lexer.addChunk('<a> '); | ||
lexer.end(); | ||
lexer.addChunk('<b> '); | ||
lexer.end(); | ||
var tokens = [], stream = new EventEmitter(), lexer = new N3Lexer(); | ||
lexer.tokenize(stream, function (error, token) { !error && tokens.push(token); }); | ||
stream.emit('data', '<a> '); | ||
stream.emit('end'); | ||
stream.emit('data', '<b> '); | ||
stream.emit('end'); | ||
@@ -680,8 +667,9 @@ it('parses only the first chunk (plus EOF)', function () { | ||
describe('passing data after an error has occured', function () { | ||
var tokens = [], lexer = new N3Lexer(); | ||
lexer.tokenize(function (error, token) { !error && tokens.push(token); }); | ||
lexer.addChunk('<a> '); | ||
lexer.addChunk('error '); | ||
lexer.end(); | ||
lexer.addChunk('<b> '); | ||
var tokens = [], stream = new EventEmitter(), lexer = new N3Lexer(); | ||
lexer.tokenize(stream, function (error, token) { !error && tokens.push(token); }); | ||
stream.emit('data', '<a> '); | ||
stream.emit('data', ' error '); | ||
stream.emit('end'); | ||
stream.emit('data', '<b> '); | ||
stream.emit('end'); | ||
@@ -692,2 +680,26 @@ it('parses only the first chunk', function () { | ||
}); | ||
describe('called with a string and without callback', function () { | ||
var lexer = new N3Lexer(), | ||
tokens = lexer.tokenize('<a> <b> <c>.'); | ||
it('returns all tokens synchronously', function () { | ||
tokens.should.deep.equal([ | ||
{ line: 1, type: 'IRI', value: 'a', prefix: '' }, | ||
{ line: 1, type: 'IRI', value: 'b', prefix: '' }, | ||
{ line: 1, type: 'IRI', value: 'c', prefix: '' }, | ||
{ line: 1, type: '.', value: '', prefix: '' }, | ||
{ line: 1, type: 'eof', value: '', prefix: '' }, | ||
]); | ||
}); | ||
}); | ||
describe('called with an erroneous string and without callback', function () { | ||
var lexer = new N3Lexer(); | ||
it('throws an error', function () { | ||
(function () { lexer.tokenize('<a> bar'); }) | ||
.should.throw('Syntax error: unexpected "bar" on line 1.'); | ||
}); | ||
}); | ||
}); | ||
@@ -741,3 +753,3 @@ }); | ||
var elements = Array.prototype.slice.call(arguments), | ||
stream = new events.EventEmitter(); | ||
stream = new EventEmitter(); | ||
@@ -744,0 +756,0 @@ stream.setEncoding = function (encoding) { |
@@ -589,2 +589,20 @@ var N3Store = require('../N3').Store; | ||
describe('An N3Store containing a blank node', function () { | ||
var store = new N3Store({ defaultGraph: 'http://example.org/#defaultGraph' }); | ||
var b1 = store.createBlankNode(); | ||
store.addTriple('s1', 'p1', b1).should.be.true; | ||
describe('when searched with more than one variable', function () { | ||
it('should return a triple with the blank node as an object', | ||
shouldIncludeAll(store.find(), | ||
['s1', 'p1', b1, store.defaultGraph])); | ||
}); | ||
describe('when searched with one variable', function () { | ||
it('should return a triple with the blank node as an object', | ||
shouldIncludeAll(store.find('s1', 'p1'), | ||
['s1', 'p1', b1, store.defaultGraph])); | ||
}); | ||
}); | ||
describe('An N3Store', function () { | ||
@@ -591,0 +609,0 @@ var store = new N3Store(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
312544
0.6%5638
0.64%392
-4.39%