New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

n3

Package Overview
Dependencies
Maintainers
1
Versions
127
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

n3 - npm Package Compare versions

Comparing version 0.11.3 to 1.0.0-alpha

lib/IRIs.js

57

lib/N3Lexer.js
// **N3Lexer** tokenizes N3 documents.
var xsd = require('./IRIs').xsd;
var fromCharCode = String.fromCharCode;

@@ -52,5 +54,5 @@ var immediately = typeof setImmediate === 'function' ? setImmediate :

_unescapedIri: /^<([^\x00-\x20<>\\"\{\}\|\^\`]*)>[ \t]*/, // IRI without escape sequences; no unescaping
_unescapedString: /^"[^"\\\r\n]+"/, // non-empty string without escape sequences
_singleQuotedString: /^"(?:[^"\\\r\n]|\\.)*"(?=[^"])|^'(?:[^'\\\r\n]|\\.)*'(?=[^'])/,
_tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/,
_unescapedString: /^"([^"\\\r\n]+)"/, // non-empty string without escape sequences
_singleQuotedString: /^"((?:[^"\\\r\n]|\\.)*)"(?=[^"])|^'((?:[^'\\\r\n]|\\.)*)'(?=[^'])/,
_tripleQuotedString: /^"""([^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*)"""|^'''([^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*)'''/,
_langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i,

@@ -106,3 +108,3 @@ _prefix: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=[#\s<])/,

var line = this._line, type = '', value = '', prefix = '',
firstChar = input[0], match = null, matchLength = 0, unescaped, inconclusive = false;
firstChar = input[0], match = null, matchLength = 0, inconclusive = false;
switch (firstChar) {

@@ -138,10 +140,10 @@ case '^':

else if (match = this._iri.exec(input)) {
unescaped = this._unescape(match[1]);
if (unescaped === null || illegalIriChars.test(unescaped))
value = this._unescape(match[1]);
if (value === null || illegalIriChars.test(value))
return reportSyntaxError(this);
type = 'IRI', value = unescaped;
type = 'IRI';
}
// Try to find a backwards implication arrow
else if (this._n3Mode && input.length > 1 && input[1] === '=')
type = 'inverse', matchLength = 2, value = 'http://www.w3.org/2000/10/swap/log#implies';
type = 'inverse', matchLength = 2, value = '>';
break;

@@ -162,20 +164,17 @@

if (match = this._unescapedString.exec(input))
type = 'literal', value = match[0];
value = match[1];
// Try to find any other literal wrapped in a pair of single or double quotes
else if (match = this._singleQuotedString.exec(input)) {
unescaped = this._unescape(match[0]);
if (unescaped === null)
return reportSyntaxError(this);
type = 'literal', value = unescaped.replace(/^'|'$/g, '"');
}
else if (match = this._singleQuotedString.exec(input))
value = this._unescape(typeof match[1] === 'string' ? match[1] : match[2]);
// Try to find a literal wrapped in three pairs of single or double quotes
else if (match = this._tripleQuotedString.exec(input)) {
unescaped = match[1] || match[2];
// Count the newlines and advance line counter
this._line += unescaped.split(/\r\n|\r|\n/).length - 1;
unescaped = this._unescape(unescaped);
if (unescaped === null)
return reportSyntaxError(this);
type = 'literal', value = unescaped.replace(/^'|'$/g, '"');
value = typeof match[1] === 'string' ? match[1] : match[2];
// Advance line counter
this._line += value.split(/\r\n|\r|\n/).length - 1;
value = this._unescape(value);
}
if (value === null)
return reportSyntaxError(this);
if (match !== null)
type = 'literal';
break;

@@ -224,5 +223,5 @@

inputFinished && (match = this._number.exec(input + ' '))) {
type = 'literal';
value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#' +
(match[1] ? 'double' : (/^[+\-]?\d+$/.test(match[0]) ? 'integer' : 'decimal'));
type = 'literal', value = match[0];
prefix = (match[1] ? xsd.double :
(/^[+\-]?\d+$/.test(match[0]) ? xsd.integer : xsd.decimal));
}

@@ -248,3 +247,3 @@ break;

if (match = this._boolean.exec(input))
type = 'literal', value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#boolean';
type = 'literal', value = match[0], prefix = xsd.boolean;
else

@@ -257,3 +256,3 @@ inconclusive = true;

if (match = this._shortPredicates.exec(input))
type = 'abbreviation', value = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
type = 'abbreviation', value = 'a';
else

@@ -268,5 +267,5 @@ inconclusive = true;

if (input[1] !== '>')
matchLength = 1, value = 'http://www.w3.org/2002/07/owl#sameAs';
matchLength = 1, value = '=';
else
matchLength = 2, value = 'http://www.w3.org/2000/10/swap/log#implies';
matchLength = 2, value = '>';
}

@@ -273,0 +272,0 @@ break;

// **N3Parser** parses N3 documents.
var N3Lexer = require('./N3Lexer');
var N3Lexer = require('./N3Lexer'),
DataFactory = require('./N3DataFactory'),
namespaces = require('./IRIs');
var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
RDF_NIL = RDF_PREFIX + 'nil',
RDF_FIRST = RDF_PREFIX + 'first',
RDF_REST = RDF_PREFIX + 'rest';
var QUANTIFIERS_GRAPH = 'urn:n3:quantifiers';
// Regexes for IRIs
var absoluteIRI = /^[a-z][a-z0-9+.-]*:/i,

@@ -27,3 +23,4 @@ schemeAuthority = /^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i,

options = options || {};
this._setBase(options.documentIRI);
this._setBase(options.baseIRI);
options.factory && initDataFactory(this, options.factory);

@@ -49,3 +46,3 @@ // Set supported features depending on the format

this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' :
'_:' + options.blankNodePrefix.replace(/^_:/, '');
options.blankNodePrefix.replace(/^(?!_:)/, '_:');
this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 });

@@ -66,2 +63,7 @@ // Disable explicit quantifiers by default

// ### `_blank` creates a new blank node
_blank: function () {
return this._blankNode('b' + blankNodeCount++);
},
// ### `_setBase` sets the base IRI to resolve relative IRIs

@@ -103,3 +105,3 @@ _setBase: function (baseIRI) {

// (using a dot as separator, as a blank node label cannot start with it)
this._prefixes._ = this._graph + '.';
this._prefixes._ = (this._graph ? this._graph.id.substr(2) + '.' : '.');
// Quantifiers are scoped to a formula

@@ -168,8 +170,7 @@ this._quantified = Object.create(this._quantified);

case 'typeIRI':
value = (this._base === null || absoluteIRI.test(token.value)) ?
token.value : this._resolveIRI(token);
value = this._namedNode(this._base === null || absoluteIRI.test(token.value) ?
token.value : this._resolveIRI(token));
break;
// Read a blank node or prefixed name
// Read a prefixed name
case 'type':
case 'blank':
case 'prefixed':

@@ -179,7 +180,12 @@ var prefix = this._prefixes[token.prefix];

return this._error('Undefined prefix "' + token.prefix + ':"', token);
value = prefix + token.value;
value = this._namedNode(prefix + token.value);
break;
// Read a blank node
case 'blank':
value = this._blankNode(this._prefixes[token.prefix] + token.value);
break;
// Read a variable
case 'var':
return token.value;
value = this._variable(token.value.substr(1));
break;
// Everything else is not an entity

@@ -190,8 +196,8 @@ default:

// In N3 mode, replace the entity if it is quantified
if (!quantifier && this._n3Mode && (value in this._quantified))
value = this._quantified[value];
if (!quantifier && this._n3Mode && (value.id in this._quantified))
value = this._quantified[value.id];
return value;
},
// ### `_readSubject` reads a triple's subject
// ### `_readSubject` reads a quad's subject
_readSubject: function (token) {

@@ -201,9 +207,9 @@ this._predicate = null;

case '[':
// Start a new triple with a new blank node as subject
// Start a new quad with a new blank node as subject
this._saveContext('blank', this._graph,
this._subject = '_:b' + blankNodeCount++, null, null);
this._subject = this._blank(), null, null);
return this._readBlankNodeHead;
case '(':
// Start a new list
this._saveContext('list', this._graph, RDF_NIL, null, null);
this._saveContext('list', this._graph, this.RDF_NIL, null, null);
this._subject = null;

@@ -216,3 +222,3 @@ return this._readListItem;

this._saveContext('formula', this._graph,
this._graph = '_:b' + blankNodeCount++, null, null);
this._graph = this._blank(), null, null);
return this._readSubject;

@@ -226,4 +232,4 @@ case '}':

this._subject = null;
this._predicate = 'http://www.w3.org/2000/10/swap/reify#forSome';
this._quantifiedPrefix = '_:b';
this._predicate = this.N3_FORSOME;
this._quantifier = this._blankNode;
return this._readQuantifierList;

@@ -234,4 +240,4 @@ case '@forAll':

this._subject = null;
this._predicate = 'http://www.w3.org/2000/10/swap/reify#forAll';
this._quantifiedPrefix = '?b-';
this._predicate = this.N3_FORALL;
this._quantifier = this._variable;
return this._readQuantifierList;

@@ -252,3 +258,3 @@ default:

// ### `_readPredicate` reads a triple's predicate
// ### `_readPredicate` reads a quad's predicate
_readPredicate: function (token) {

@@ -260,3 +266,3 @@ var type = token.type;

case 'abbreviation':
this._predicate = token.value;
this._predicate = this.ABBREVIATIONS[token.value];
break;

@@ -286,16 +292,21 @@ case '.':

// ### `_readObject` reads a triple's object
// ### `_readObject` reads a quad's object
_readObject: function (token) {
switch (token.type) {
case 'literal':
this._object = token.value;
return this._readDataTypeOrLang;
// Regular literal, can still get a datatype or language
if (token.prefix.length === 0)
return this._readDataTypeOrLang;
// Pre-datatyped string literal (prefix stores the datatype)
else
this._object = this._literal(token.value, this._namedNode(token.prefix));
break;
case '[':
// Start a new triple with a new blank node as subject
// Start a new quad with a new blank node as subject
this._saveContext('blank', this._graph, this._subject, this._predicate,
this._subject = '_:b' + blankNodeCount++);
this._subject = this._blank());
return this._readBlankNodeHead;
case '(':
// Start a new list
this._saveContext('list', this._graph, this._subject, this._predicate, RDF_NIL);
this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
this._subject = null;

@@ -308,3 +319,3 @@ return this._readListItem;

this._saveContext('formula', this._graph, this._subject, this._predicate,
this._graph = '_:b' + blankNodeCount++);
this._graph = this._blank());
return this._readSubject;

@@ -322,3 +333,3 @@ default:

// ### `_readPredicateOrNamedGraph` reads a triple's predicate, or a named graph
// ### `_readPredicateOrNamedGraph` reads a quad's predicate, or a named graph
_readPredicateOrNamedGraph: function (token) {

@@ -354,5 +365,5 @@ return token.type === '{' ? this._readGraph(token) : this._readPredicate(token);

// Store blank node triple
// Store blank node quad
if (this._subject !== null)
this._triple(this._subject, this._predicate, this._object, this._graph);
this._emit(this._subject, this._predicate, this._object, this._graph);

@@ -375,3 +386,3 @@ // Restore the parent context containing this blank node

if (token.type === '.' && !this._contextStack.length) {
this._subject = null; // cancel the current triple
this._subject = null; // cancel the current quad
return this._readPunctuation(token);

@@ -389,16 +400,16 @@ }

parent = stack[stack.length - 1], // The parent containing the current list
next = this._readListItem, // The next function to execute
itemComplete = true; // Whether the item has been read fully
next = this._readListItem; // The next function to execute
switch (token.type) {
case '[':
// Stack the current list triple and start a new triple with a blank node as subject
this._saveContext('blank', this._graph, list = '_:b' + blankNodeCount++,
RDF_FIRST, this._subject = item = '_:b' + blankNodeCount++);
// Stack the current list quad and start a new quad with a blank node as subject
this._saveContext('blank', this._graph,
list = this._blank(), this.RDF_FIRST,
this._subject = item = this._blank());
next = this._readBlankNodeHead;
break;
case '(':
// Stack the current list triple and start a new list
this._saveContext('list', this._graph, list = '_:b' + blankNodeCount++,
RDF_FIRST, RDF_NIL);
// Stack the current list quad and start a new list
this._saveContext('list', this._graph,
list = this._blank(), this.RDF_FIRST, this.RDF_NIL);
this._subject = null;

@@ -409,6 +420,6 @@ break;

this._restoreContext();
// If this list is contained within a parent list, return the membership triple here.
// If this list is contained within a parent list, return the membership quad here.
// This will be `<parent list element> rdf:first <this list>.`.
if (stack.length !== 0 && stack[stack.length - 1].type === 'list')
this._triple(this._subject, this._predicate, this._object, this._graph);
this._emit(this._subject, this._predicate, this._object, this._graph);
// Was this list the parent's subject?

@@ -419,3 +430,3 @@ if (this._predicate === null) {

// No list tail if this was an empty list
if (this._subject === RDF_NIL)
if (this._subject === this.RDF_NIL)
return next;

@@ -427,12 +438,17 @@ }

// No list tail if this was an empty list
if (this._object === RDF_NIL)
if (this._object === this.RDF_NIL)
return next;
}
// Close the list by making the head nil
list = RDF_NIL;
list = this.RDF_NIL;
break;
case 'literal':
item = token.value;
itemComplete = false; // Can still have a datatype or language
next = this._readListItemDataTypeOrLang;
// Regular literal, can still get a datatype or language
if (token.prefix.length === 0)
next = this._readListItemDataTypeOrLang;
// Pre-datatyped string literal (prefix stores the datatype)
else {
item = this._literal(token.value, this._namedNode(token.prefix));
next = this._getContextEndReader();
}
break;

@@ -446,3 +462,3 @@ default:

if (list === null)
this._subject = list = '_:b' + blankNodeCount++;
this._subject = list = this._blank();

@@ -459,5 +475,5 @@ // Is this the first element of the list?

// Continue the previous list with the current list
this._triple(prevList, RDF_REST, list, this._graph);
this._emit(prevList, this.RDF_REST, list, this._graph);
}
// Add the item's value
// If an item was read, add it to the list
if (item !== null) {

@@ -467,3 +483,3 @@ // In N3 mode, the item might be a path

// Create a new context to add the item's path
this._saveContext('item', this._graph, list, RDF_FIRST, item);
this._saveContext('item', this._graph, list, this.RDF_FIRST, item);
this._subject = item, this._predicate = null;

@@ -473,8 +489,4 @@ // _readPath will restore the context and output the item

}
// Output the item if it is complete
if (itemComplete)
this._triple(list, RDF_FIRST, item, this._graph);
// Otherwise, save it for completion
else
this._object = item;
// Output the item
this._emit(list, this.RDF_FIRST, item, this._graph);
}

@@ -484,3 +496,3 @@ return next;

// ### `_readDataTypeOrLang` reads an _optional_ data type or language
// ### `_readDataTypeOrLang` reads an _optional_ datatype or language
_readDataTypeOrLang: function (token) {

@@ -490,3 +502,3 @@ return this._completeLiteral(token, false);

// ### `_readListItemDataTypeOrLang` reads an _optional_ data type or language in a list
// ### `_readListItemDataTypeOrLang` reads an _optional_ datatype or language in a list
_readListItemDataTypeOrLang: function (token) {

@@ -496,20 +508,22 @@ return this._completeLiteral(token, true);

// ### `_completeLiteral` completes the object with a data type or language
// ### `_completeLiteral` completes a literal with an optional datatype or language
_completeLiteral: function (token, listItem) {
var suffix = false;
var value = this._lexer.previousToken.value;
switch (token.type) {
// Add a "^^type" suffix for types (IRIs and blank nodes)
// Create a datatyped literal
case 'type':
case 'typeIRI':
var datatype = this._readEntity(token);
// No datatype means an error was reported, so abort
if (datatype === undefined) return;
suffix = true;
this._object += '^^' + datatype;
if (datatype === undefined) return; // No datatype means an error occurred
this._object = this._literal(value, datatype);
token = null;
break;
// Add an "@lang" suffix for language tags
// Create a language-tagged string
case 'langcode':
suffix = true;
this._object += '@' + token.value.toLowerCase();
this._object = this._literal(value, token.value);
token = null;
break;
// Create a simple string literal
default:
this._object = this._literal(value);
}

@@ -519,6 +533,7 @@ // If this literal was part of a list, write the item

if (listItem)
this._triple(this._subject, RDF_FIRST, this._object, this._graph);
// Continue with the rest of the input
if (suffix)
this._emit(this._subject, this.RDF_FIRST, this._object, this._graph);
// If the token was consumed, continue with the rest of the input
if (token === null)
return this._getContextEndReader();
// Otherwise, consume the token now
else {

@@ -535,5 +550,5 @@ this._readCallback = this._getContextEndReader();

// Store the last triple of the formula
// Store the last quad of the formula
if (this._subject !== null)
this._triple(this._subject, this._predicate, this._object, this._graph);
this._emit(this._subject, this._predicate, this._object, this._graph);

@@ -547,3 +562,3 @@ // Restore the parent context containing this formula

// ### `_readPunctuation` reads punctuation between triples or triple parts
// ### `_readPunctuation` reads punctuation between quads or quad parts
_readPunctuation: function (token) {

@@ -580,11 +595,11 @@ var next, subject = this._subject, graph = this._graph,

}
return this._error('Expected punctuation to follow "' + this._object + '"', token);
return this._error('Expected punctuation to follow "' + this._object.id + '"', token);
}
// A triple has been completed now, so return it
// A quad has been completed now, so return it
if (subject !== null) {
var predicate = this._predicate, object = this._object;
if (!inversePredicate)
this._triple(subject, predicate, object, graph);
this._emit(subject, predicate, object, graph);
else
this._triple(object, predicate, subject, graph);
this._emit(object, predicate, subject, graph);
}

@@ -607,6 +622,6 @@ return next;

default:
return this._error('Expected punctuation to follow "' + this._object + '"', token);
return this._error('Expected punctuation to follow "' + this._object.id + '"', token);
}
// A triple has been completed now, so return it
this._triple(this._subject, this._predicate, this._object, this._graph);
// A quad has been completed now, so return it
this._emit(this._subject, this._predicate, this._object, this._graph);
return next;

@@ -634,5 +649,5 @@ },

return this._error('Expected IRI to follow prefix "' + this._prefix + ':"', token);
var prefixIRI = this._readEntity(token);
this._prefixes[this._prefix] = prefixIRI;
this._prefixCallback(this._prefix, prefixIRI);
var prefixNode = this._readEntity(token);
this._prefixes[this._prefix] = prefixNode.value;
this._prefixCallback(this._prefix, prefixNode);
return this._readDeclarationPunctuation;

@@ -668,3 +683,3 @@ },

return this._error('Invalid graph label', token);
this._subject = '_:b' + blankNodeCount++;
this._subject = this._blank();
return this._readGraph;

@@ -699,3 +714,3 @@ },

if (!this._explicitQuantifiers)
this._quantified[entity] = this._quantifiedPrefix + blankNodeCount++;
this._quantified[entity.id] = this._quantifier('b' + blankNodeCount++);
// With explicit quantifiers, output the reified quantifier

@@ -705,10 +720,10 @@ else {

if (this._subject === null)
this._triple(this._graph || '', this._predicate,
this._subject = '_:b' + blankNodeCount++, QUANTIFIERS_GRAPH);
this._emit(this._graph || this.DEFAULTGRAPH, this._predicate,
this._subject = this._blank(), this.QUANTIFIERS_GRAPH);
// Otherwise, continue the previous list
else
this._triple(this._subject, RDF_REST,
this._subject = '_:b' + blankNodeCount++, QUANTIFIERS_GRAPH);
this._emit(this._subject, this.RDF_REST,
this._subject = this._blank(), this.QUANTIFIERS_GRAPH);
// Output the list item
this._triple(this._subject, RDF_FIRST, entity, QUANTIFIERS_GRAPH);
this._emit(this._subject, this.RDF_FIRST, entity, this.QUANTIFIERS_GRAPH);
}

@@ -727,3 +742,3 @@ return this._readQuantifierPunctuation;

if (this._explicitQuantifiers) {
this._triple(this._subject, RDF_REST, RDF_NIL, QUANTIFIERS_GRAPH);
this._emit(this._subject, this.RDF_REST, this.RDF_NIL, this.QUANTIFIERS_GRAPH);
this._subject = null;

@@ -760,3 +775,3 @@ }

// Output the list item
this._triple(this._subject, RDF_FIRST, item, this._graph);
this._emit(this._subject, this.RDF_FIRST, item, this._graph);
}

@@ -769,3 +784,3 @@ return this._afterPath(token);

_readForwardPath: function (token) {
var subject, predicate, object = '_:b' + blankNodeCount++;
var subject, predicate, object = this._blank();
// The next token is the predicate

@@ -780,4 +795,4 @@ if ((predicate = this._readEntity(token)) === undefined)

subject = this._object, this._object = object;
// Emit the path's current triple and read its next section
this._triple(subject, predicate, object, this._graph);
// Emit the path's current quad and read its next section
this._emit(subject, predicate, object, this._graph);
return this._readPath;

@@ -788,3 +803,3 @@ },

_readBackwardPath: function (token) {
var subject = '_:b' + blankNodeCount++, predicate, object;
var subject = this._blank(), predicate, object;
// The next token is the predicate

@@ -799,4 +814,4 @@ if ((predicate = this._readEntity(token)) === undefined)

object = this._object, this._object = subject;
// Emit the path's current triple and read its next section
this._triple(subject, predicate, object, this._graph);
// Emit the path's current quad and read its next section
this._emit(subject, predicate, object, this._graph);
return this._readPath;

@@ -821,6 +836,5 @@ },

// ### `_triple` emits a triple through the callback
_triple: function (subject, predicate, object, graph) {
this._callback(null,
{ subject: subject, predicate: predicate, object: object, graph: graph || '' });
// ### `_emit` sends a quad through the callback
_emit: function (subject, predicate, object, graph) {
this._callback(null, this._quad(subject, predicate, object, graph || this.DEFAULTGRAPH));
},

@@ -925,4 +939,4 @@

// ### `parse` parses the N3 input and emits each parsed triple through the callback
parse: function (input, tripleCallback, prefixCallback) {
// ### `parse` parses the N3 input and emits each parsed quad through the callback
parse: function (input, quadCallback, prefixCallback) {
var self = this;

@@ -934,3 +948,4 @@ // The read callback is the next function to be executed when a token arrives.

this._prefixes = Object.create(null);
this._prefixes._ = this._blankNodePrefix || '_:b' + blankNodePrefix++ + '_';
this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
: 'b' + blankNodePrefix++ + '_';
this._prefixCallback = prefixCallback || noop;

@@ -940,6 +955,6 @@ this._inversePredicate = false;

// Parse synchronously if no triple callback is given
if (!tripleCallback) {
var triples = [], error;
this._callback = function (e, t) { e ? (error = e) : t && triples.push(t); };
// Parse synchronously if no quad callback is given
if (!quadCallback) {
var quads = [], error;
this._callback = function (e, t) { e ? (error = e) : t && quads.push(t); };
this._lexer.tokenize(input).every(function (token) {

@@ -949,7 +964,7 @@ return self._readCallback = self._readCallback(token);

if (error) throw error;
return triples;
return quads;
}
// Parse asynchronously otherwise, executing the read callback when a token arrives
this._callback = tripleCallback;
this._callback = quadCallback;
this._lexer.tokenize(input, function (error, token) {

@@ -967,3 +982,29 @@ if (error !== null)

// Initializes the parser with the given data factory
function initDataFactory(parser, factory) {
// Set factory methods
var namedNode = factory.namedNode;
parser._namedNode = namedNode;
parser._blankNode = factory.blankNode;
parser._literal = factory.literal;
parser._variable = factory.variable;
parser._quad = factory.quad;
parser.DEFAULTGRAPH = factory.defaultGraph();
// Set common named nodes
parser.RDF_FIRST = namedNode(namespaces.rdf.first);
parser.RDF_REST = namedNode(namespaces.rdf.rest);
parser.RDF_NIL = namedNode(namespaces.rdf.nil);
parser.N3_FORALL = namedNode(namespaces.r.forAll);
parser.N3_FORSOME = namedNode(namespaces.r.forSome);
parser.ABBREVIATIONS = {
'a': namedNode(namespaces.rdf.type),
'=': namedNode(namespaces.owl.sameAs),
'>': namedNode(namespaces.log.implies),
};
parser.QUANTIFIERS_GRAPH = namedNode('urn:n3:quantifiers');
}
initDataFactory(N3Parser.prototype, DataFactory);
// ## Exports
module.exports = N3Parser;

@@ -1,11 +0,13 @@

// **N3Store** objects store N3 triples by graph in memory.
// **N3Store** objects store N3 quads by graph in memory.
var expandPrefixedName = require('./N3Util').expandPrefixedName;
var DataFactory = require('./N3DataFactory');
var toId = DataFactory.internal.toId,
fromId = DataFactory.internal.fromId;
// ## Constructor
function N3Store(triples, options) {
function N3Store(quads, options) {
if (!(this instanceof N3Store))
return new N3Store(triples, options);
return new N3Store(quads, options);
// The number of triples is initially zero
// The number of quads is initially zero
this._size = 0;

@@ -23,13 +25,11 @@ // `_graphs` contains subject, predicate, and object indexes per graph

// Shift parameters if `triples` is not given
if (!options && triples && !triples[0])
options = triples, triples = null;
// Shift parameters if `quads` is not given
if (!options && quads && !quads[0])
options = quads, quads = null;
options = options || {};
this._factory = options.factory || DataFactory;
// Add triples and prefixes if passed
this._prefixes = Object.create(null);
if (options.prefixes)
this.addPrefixes(options.prefixes);
if (triples)
this.addTriples(triples);
// Add quads if passed
if (quads)
this.addQuads(quads);
}

@@ -40,5 +40,5 @@

// ### `size` returns the number of triples in the store
// ### `size` returns the number of quads in the store
get size() {
// Return the triple count if if was cached
// Return the quad count if if was cached
var size = this._size;

@@ -48,3 +48,3 @@ if (size !== null)

// Calculate the number of triples by counting to the deepest level
// Calculate the number of quads by counting to the deepest level
size = 0;

@@ -61,3 +61,3 @@ var graphs = this._graphs, subjects, subject;

// ### `_addToIndex` adds a triple to a three-layered index.
// ### `_addToIndex` adds a quad to a three-layered index.
// Returns if the index has changed, if the entry did not already exist.

@@ -68,3 +68,3 @@ _addToIndex: function (index0, key0, key1, key2) {

var index2 = index1[key1] || (index1[key1] = {});
// Setting the key to _any_ value signals the presence of the triple
// Setting the key to _any_ value signals the presence of the quad
var existed = key2 in index2;

@@ -76,5 +76,5 @@ if (!existed)

// ### `_removeFromIndex` removes a triple from a three-layered index
// ### `_removeFromIndex` removes a quad from a three-layered index
_removeFromIndex: function (index0, key0, key1, key2) {
// Remove the triple from the index
// Remove the quad from the index
var index1 = index0[key0], index2 = index1[key1], key;

@@ -90,11 +90,11 @@ delete index2[key2];

// ### `_findInIndex` finds a set of triples in a three-layered index.
// ### `_findInIndex` finds a set of quads in a three-layered index.
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.
// Any of these keys can be undefined, which is interpreted as a wildcard.
// `name0`, `name1`, and `name2` are the names of the keys at each level,
// used when reconstructing the resulting triple
// used when reconstructing the resulting quad
// (for instance: _subject_, _predicate_, and _object_).
// Finally, `graph` will be the graph of the created triples.
// Finally, `graph` will be the graph of the created quads.
// If `callback` is given, each result is passed through it
// and iteration halts when it returns truthy for any triple.
// and iteration halts when it returns truthy for any quad.
// If instead `array` is given, each result is added to the array.

@@ -120,11 +120,13 @@ _findInIndex: function (index0, key0, key1, key2, name0, name1, name2, graph, callback, array) {

var values = key2 ? (key2 in index2 ? [key2] : []) : Object.keys(index2);
// Create triples for all items found in index 2.
for (var l = values.length - 1; l >= 0; l--) {
var result = { subject: '', predicate: '', object: '', graph: graph };
result[name0] = entity0;
result[name1] = entity1;
result[name2] = entityKeys[values[l]];
// Create quads for all items found in index 2.
for (var l = 0; l < values.length; l++) {
var parts = { subject: null, predicate: null, object: null };
parts[name0] = fromId(entity0, this._factory);
parts[name1] = fromId(entity1, this._factory);
parts[name2] = fromId(entityKeys[values[l]], this._factory);
var quad = this._factory.quad(
parts.subject, parts.predicate, parts.object, fromId(graph, this._factory));
if (array)
array.push(result);
else if (callback(result))
array.push(quad);
else if (callback(quad))
return true;

@@ -173,3 +175,3 @@ }

// ### `_countInIndex` counts matching triples in a three-layered index.
// ### `_countInIndex` counts matching quads in a three-layered index.
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.

@@ -188,5 +190,5 @@ // Any of these keys can be undefined, which is interpreted as a wildcard.

if (index2 = index1[value1]) {
// If a key is specified, count the triple if it exists
// If a key is specified, count the quad if it exists
if (key2) (key2 in index2) && count++;
// Otherwise, count all triples
// Otherwise, count all quads
else count += Object.keys(index2).length;

@@ -217,3 +219,3 @@ }

uniqueIds[id] = true;
callback(entities[id]);
callback(fromId(entities[id]));
}

@@ -225,6 +227,6 @@ };

// ### `addTriple` adds a new N3 triple to the store.
// Returns if the triple index has changed, if the triple did not already exist.
addTriple: function (subject, predicate, object, graph) {
// Shift arguments if a triple object is given instead of components
// ### `addQuad` adds a new quad to the store.
// Returns if the quad index has changed, if the quad did not already exist.
addQuad: function (subject, predicate, object, graph) {
// Shift arguments if a quad object is given instead of components
if (!predicate)

@@ -234,4 +236,9 @@ graph = subject.graph, object = subject.object,

// Convert terms to internal string representation
subject = toId(subject);
predicate = toId(predicate);
object = toId(object);
graph = toId(graph);
// Find the graph that will contain the triple
graph = graph || '';
var graphItem = this._graphs[graph];

@@ -259,3 +266,3 @@ // Create the graph if it doesn't exist yet

// The cached triple count is now invalid
// The cached quad count is now invalid
this._size = null;

@@ -265,29 +272,30 @@ return changed;

// ### `addTriples` adds multiple N3 triples to the store
addTriples: function (triples) {
for (var i = triples.length - 1; i >= 0; i--)
this.addTriple(triples[i]);
// ### `addQuads` adds multiple quads to the store
addQuads: function (quads) {
for (var i = 0; i < quads.length; i++)
this.addQuad(quads[i]);
},
// ### `addPrefix` adds support for querying with the given prefix
addPrefix: function (prefix, iri) {
this._prefixes[prefix] = iri;
// ### `import` adds a stream of quads to the store
import: function (stream) {
var self = this;
stream.on('data', function (quad) { self.addQuad(quad); });
return stream;
},
// ### `addPrefixes` adds support for querying with the given prefixes
addPrefixes: function (prefixes) {
for (var prefix in prefixes)
this.addPrefix(prefix, prefixes[prefix]);
},
// ### `removeTriple` removes an N3 triple from the store if it exists
removeTriple: function (subject, predicate, object, graph) {
// Shift arguments if a triple object is given instead of components
// ### `removeQuad` removes a quad from the store if it exists
removeQuad: function (subject, predicate, object, graph) {
// Shift arguments if a quad object is given instead of components
if (!predicate)
graph = subject.graph, object = subject.object,
predicate = subject.predicate, subject = subject.subject;
graph = graph || '';
// Convert terms to internal string representation
subject = toId(subject);
predicate = toId(predicate);
object = toId(object);
graph = toId(graph);
// Find internal identifiers for all components
// and verify the triple exists.
// and verify the quad exists.
var graphItem, ids = this._ids, graphs = this._graphs, subjects, predicates;

@@ -313,23 +321,24 @@ if (!(subject = ids[subject]) || !(predicate = ids[predicate]) ||

// ### `removeTriples` removes multiple N3 triples from the store
removeTriples: function (triples) {
for (var i = triples.length - 1; i >= 0; i--)
this.removeTriple(triples[i]);
// ### `removeQuads` removes multiple quads from the store
removeQuads: function (quads) {
for (var i = 0; i < quads.length; i++)
this.removeQuad(quads[i]);
},
// ### `getTriples` returns an array of triples matching a pattern, expanding prefixes as necessary.
// Setting any field to `undefined` or `null` indicates a wildcard.
getTriples: function (subject, predicate, object, graph) {
var prefixes = this._prefixes;
return this.getTriplesByIRI(
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
// ### `remove` removes a stream of quads from the store
remove: function (stream) {
var self = this;
stream.on('data', function (quad) { self.removeQuad(quad); });
return stream;
},
// ### `getTriplesByIRI` returns an array of triples matching a pattern.
// ### `getQuads` returns an array of quads matching a pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
getTriplesByIRI: function (subject, predicate, object, graph) {
getQuads: function (subject, predicate, object, graph) {
// Convert terms to internal string representation
subject = subject && toId(subject);
predicate = predicate && toId(predicate);
object = object && toId(object);
graph = graph && toId(graph);
var quads = [], graphs = this._getGraphs(graph), content,

@@ -375,17 +384,11 @@ ids = this._ids, subjectId, predicateId, objectId;

// ### `countTriples` returns the number of triples matching a pattern, expanding prefixes as necessary.
// ### `countQuads` returns the number of quads matching a pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
countTriples: function (subject, predicate, object, graph) {
var prefixes = this._prefixes;
return this.countTriplesByIRI(
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
countQuads: function (subject, predicate, object, graph) {
// Convert terms to internal string representation
subject = subject && toId(subject);
predicate = predicate && toId(predicate);
object = object && toId(object);
graph = graph && toId(graph);
// ### `countTriplesByIRI` returns the number of triples matching a pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
countTriplesByIRI: function (subject, predicate, object, graph) {
var count = 0, graphs = this._getGraphs(graph), content,

@@ -425,19 +428,6 @@ ids = this._ids, subjectId, predicateId, objectId;

// ### `forEach` executes the callback on all triples.
// ### `forEach` executes the callback on all quads.
// Setting any field to `undefined` or `null` indicates a wildcard.
forEach: function (callback, subject, predicate, object, graph) {
var prefixes = this._prefixes;
this.forEachByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// ### `forEachByIRI` executes the callback on all triples.
// Setting any field to `undefined` or `null` indicates a wildcard.
forEachByIRI: function (callback, subject, predicate, object, graph) {
this.someByIRI(function (quad) {
this.some(function (quad) {
callback(quad);

@@ -448,22 +438,8 @@ return false;

// ### `every` executes the callback on all triples,
// ### `every` executes the callback on all quads,
// and returns `true` if it returns truthy for all them.
// Setting any field to `undefined` or `null` indicates a wildcard.
every: function (callback, subject, predicate, object, graph) {
var prefixes = this._prefixes;
return this.everyByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// ### `everyByIRI` executes the callback on all triples,
// and returns `true` if it returns truthy for all them.
// Setting any field to `undefined` or `null` indicates a wildcard.
everyByIRI: function (callback, subject, predicate, object, graph) {
var some = false;
var every = !this.someByIRI(function (quad) {
var every = !this.some(function (quad) {
some = true;

@@ -475,20 +451,12 @@ return !callback(quad);

// ### `some` executes the callback on all triples,
// ### `some` executes the callback on all quads,
// and returns `true` if it returns truthy for any of them.
// Setting any field to `undefined` or `null` indicates a wildcard.
some: function (callback, subject, predicate, object, graph) {
var prefixes = this._prefixes;
return this.someByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// Convert terms to internal string representation
subject = subject && toId(subject);
predicate = predicate && toId(predicate);
object = object && toId(object);
graph = graph && toId(graph);
// ### `someByIRI` executes the callback on all triples,
// and returns `true` if it returns truthy for any of them.
// Setting any field to `undefined` or `null` indicates a wildcard.
someByIRI: function (callback, subject, predicate, object, graph) {
var graphs = this._getGraphs(graph), content,

@@ -504,3 +472,3 @@ ids = this._ids, subjectId, predicateId, objectId;

for (var graphId in graphs) {
// Only if the specified graph contains triples, there can be result
// Only if the specified graph contains triples, there can be results
if (content = graphs[graphId]) {

@@ -549,15 +517,4 @@ // Choose the optimal index, based on what fields are present

getSubjects: function (predicate, object, graph) {
var prefixes = this._prefixes;
return this.getSubjectsByIRI(
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// ### `getSubjectsByIRI` returns all subjects that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
getSubjectsByIRI: function (predicate, object, graph) {
var results = [];
this.forSubjectsByIRI(function (s) { results.push(s); }, predicate, object, graph);
this.forSubjects(function (s) { results.push(s); }, predicate, object, graph);
return results;

@@ -569,14 +526,7 @@ },

forSubjects: function (callback, predicate, object, graph) {
var prefixes = this._prefixes;
this.forSubjectsByIRI(
callback,
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// Convert terms to internal string representation
predicate = predicate && toId(predicate);
object = object && toId(object);
graph = graph && toId(graph);
// ### `forSubjectsByIRI` executes the callback on all subjects that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
forSubjectsByIRI: function (callback, predicate, object, graph) {
var ids = this._ids, graphs = this._getGraphs(graph), content, predicateId, objectId;

@@ -615,15 +565,4 @@ callback = this._uniqueEntities(callback);

getPredicates: function (subject, object, graph) {
var prefixes = this._prefixes;
return this.getPredicatesByIRI(
expandPrefixedName(subject, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// ### `getPredicatesByIRI` returns all predicates that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
getPredicatesByIRI: function (subject, object, graph) {
var results = [];
this.forPredicatesByIRI(function (p) { results.push(p); }, subject, object, graph);
this.forPredicates(function (p) { results.push(p); }, subject, object, graph);
return results;

@@ -635,14 +574,7 @@ },

forPredicates: function (callback, subject, object, graph) {
var prefixes = this._prefixes;
this.forPredicatesByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(object, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// Convert terms to internal string representation
subject = subject && toId(subject);
object = object && toId(object);
graph = graph && toId(graph);
// ### `forPredicatesByIRI` executes the callback on all predicates that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
forPredicatesByIRI: function (callback, subject, object, graph) {
var ids = this._ids, graphs = this._getGraphs(graph), content, subjectId, objectId;

@@ -681,15 +613,4 @@ callback = this._uniqueEntities(callback);

getObjects: function (subject, predicate, graph) {
var prefixes = this._prefixes;
return this.getObjectsByIRI(
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// ### `getObjectsByIRI` returns all objects that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
getObjectsByIRI: function (subject, predicate, graph) {
var results = [];
this.forObjectsByIRI(function (o) { results.push(o); }, subject, predicate, graph);
this.forObjects(function (o) { results.push(o); }, subject, predicate, graph);
return results;

@@ -701,14 +622,7 @@ },

forObjects: function (callback, subject, predicate, graph) {
var prefixes = this._prefixes;
this.forObjectsByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(graph, prefixes)
);
},
// Convert terms to internal string representation
subject = subject && toId(subject);
predicate = predicate && toId(predicate);
graph = graph && toId(graph);
// ### `forObjectsByIRI` executes the callback on all objects that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
forObjectsByIRI: function (callback, subject, predicate, graph) {
var ids = this._ids, graphs = this._getGraphs(graph), content, subjectId, predicateId;

@@ -747,15 +661,4 @@ callback = this._uniqueEntities(callback);

getGraphs: function (subject, predicate, object) {
var prefixes = this._prefixes;
return this.getGraphsByIRI(
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes)
);
},
// ### `getGraphsByIRI` returns all graphs that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
getGraphsByIRI: function (subject, predicate, object) {
var results = [];
this.forGraphsByIRI(function (g) { results.push(g); }, subject, predicate, object);
this.forGraphs(function (g) { results.push(g); }, subject, predicate, object);
return results;

@@ -767,16 +670,4 @@ },

forGraphs: function (callback, subject, predicate, object) {
var prefixes = this._prefixes;
this.forGraphsByIRI(
callback,
expandPrefixedName(subject, prefixes),
expandPrefixedName(predicate, prefixes),
expandPrefixedName(object, prefixes)
);
},
// ### `forGraphsByIRI` executes the callback on all graphs that match the pattern.
// Setting any field to `undefined` or `null` indicates a wildcard.
forGraphsByIRI: function (callback, subject, predicate, object) {
for (var graph in this._graphs) {
this.someByIRI(function (quad) {
this.some(function (quad) {
callback(quad.graph);

@@ -805,3 +696,3 @@ return true; // Halt iteration of some()

this._entities[this._id] = name;
return name;
return this._factory.blankNode(name.substr(2));
},

@@ -808,0 +699,0 @@ };

@@ -1,2 +0,2 @@

// **N3StreamParser** parses an N3 stream into a triple stream.
// **N3StreamParser** parses a text stream into a quad stream.
var Transform = require('stream').Transform,

@@ -19,11 +19,11 @@ util = require('util'),

parser.parse({
on: function (event, cb) {
on: function (event, callback) {
switch (event) {
case 'data': onData = cb; break;
case 'end': onEnd = cb; break;
case 'data': onData = callback; break;
case 'end': onEnd = callback; break;
}
},
},
// Handle triples by pushing them down the pipeline
function (error, t) { error && self.emit('error', error) || t && self.push(t); },
// Handle quads by pushing them down the pipeline
function (error, quad) { error && self.emit('error', error) || quad && self.push(quad); },
// Emit prefixes through the `prefix` event

@@ -38,3 +38,12 @@ function (prefix, uri) { self.emit('prefix', prefix, uri); });

// ### Parses a stream of strings
N3StreamParser.prototype.import = function (stream) {
var self = this;
stream.on('data', function (chunk) { self.write(chunk); });
stream.on('end', function () { self.end(); });
stream.on('error', function (error) { self.emit('error', error); });
return this;
};
// ## Exports
module.exports = N3StreamParser;

@@ -1,2 +0,2 @@

// **N3StreamWriter** serializes a triple stream into an N3 stream.
// **N3StreamWriter** serializes a quad stream into a text stream.
var Transform = require('stream').Transform,

@@ -17,4 +17,4 @@ util = require('util'),

var self = this;
var writer = new N3Writer({
write: function (chunk, encoding, callback) { self.push(chunk); callback && callback(); },
var writer = this._writer = new N3Writer({
write: function (quad, encoding, callback) { self.push(quad); callback && callback(); },
end: function (callback) { self.push(null); callback && callback(); },

@@ -24,3 +24,3 @@ }, options);

// Implement Transform methods on top of writer
this._transform = function (triple, encoding, done) { writer.addTriple(triple, done); };
this._transform = function (quad, encoding, done) { writer.addQuad(quad, done); };
this._flush = function (done) { writer.end(done); };

@@ -30,3 +30,13 @@ }

// ### Serializes a stream of quads
N3StreamWriter.prototype.import = function (stream) {
var self = this;
stream.on('data', function (quad) { self.write(quad); });
stream.on('end', function () { self.end(); });
stream.on('error', function (error) { self.emit('error', error); });
stream.on('prefix', function (prefix, iri) { self._writer.addPrefix(prefix, iri); });
return this;
};
// ## Exports
module.exports = N3StreamWriter;
// **N3Util** provides N3 utility functions.
var Xsd = 'http://www.w3.org/2001/XMLSchema#';
var XsdString = Xsd + 'string';
var XsdInteger = Xsd + 'integer';
var XsdDouble = Xsd + 'double';
var XsdBoolean = Xsd + 'boolean';
var RdfLangString = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString';
var DataFactory = require('./N3DataFactory');
var N3Util = {
// Tests whether the given entity (triple object) represents an IRI in the N3 library
isIRI: function (entity) {
if (typeof entity !== 'string')
return false;
else if (entity.length === 0)
return true;
else {
var firstChar = entity[0];
return firstChar !== '"' && firstChar !== '_';
}
// Tests whether the given term represents an IRI
isNamedNode: function (term) {
return !!term && term.termType === 'NamedNode';
},
// Tests whether the given entity (triple object) represents a literal in the N3 library
isLiteral: function (entity) {
return typeof entity === 'string' && entity[0] === '"';
// Tests whether the given term represents a blank node
isBlankNode: function (term) {
return !!term && term.termType === 'BlankNode';
},
// Tests whether the given entity (triple object) represents a blank node in the N3 library
isBlank: function (entity) {
return typeof entity === 'string' && entity.substr(0, 2) === '_:';
// Tests whether the given term represents a literal
isLiteral: function (term) {
return !!term && term.termType === 'Literal';
},
// Tests whether the given entity represents the default graph
isDefaultGraph: function (entity) {
return !entity;
// Tests whether the given term represents a variable
isVariable: function (term) {
return !!term && term.termType === 'Variable';
},
// Tests whether the given triple is in the default graph
inDefaultGraph: function (triple) {
return !triple.graph;
// Tests whether the given term represents the default graph
isDefaultGraph: function (term) {
return !!term && term.termType === 'DefaultGraph';
},
// Gets the string value of a literal in the N3 library
getLiteralValue: function (literal) {
var match = /^"([^]*)"/.exec(literal);
if (!match)
throw new Error(literal + ' is not a literal');
return match[1];
// Tests whether the given quad is in the default graph
inDefaultGraph: function (quad) {
return N3Util.isDefaultGraph(quad.graph);
},
// Gets the type of a literal in the N3 library
getLiteralType: function (literal) {
var match = /^"[^]*"(?:\^\^([^"]+)|(@)[^@"]+)?$/.exec(literal);
if (!match)
throw new Error(literal + ' is not a literal');
return match[1] || (match[2] ? RdfLangString : XsdString);
},
// Gets the language of a literal in the N3 library
getLiteralLanguage: function (literal) {
var match = /^"[^]*"(?:@([^@"]+)|\^\^[^"]+)?$/.exec(literal);
if (!match)
throw new Error(literal + ' is not a literal');
return match[1] ? match[1].toLowerCase() : '';
},
// Tests whether the given entity (triple object) represents a prefixed name
isPrefixedName: function (entity) {
return typeof entity === 'string' && /^[^:\/"']*:[^:\/"']+$/.test(entity);
},
// Expands the prefixed name to a full IRI (also when it occurs as a literal's type)
expandPrefixedName: function (prefixedName, prefixes) {
var match = /(?:^|"\^\^)([^:\/#"'\^_]*):[^\/]*$/.exec(prefixedName), prefix, base, index;
if (match)
prefix = match[1], base = prefixes[prefix], index = match.index;
if (base === undefined)
return prefixedName;
// The match index is non-zero when expanding a literal's type
return index === 0 ? base + prefixedName.substr(prefix.length + 1)
: prefixedName.substr(0, index + 3) +
base + prefixedName.substr(index + prefix.length + 4);
},
// Creates an IRI in N3.js representation
createIRI: function (iri) {
return iri && iri[0] === '"' ? N3Util.getLiteralValue(iri) : iri;
},
// Creates a literal in N3.js representation
createLiteral: function (value, modifier) {
if (!modifier) {
switch (typeof value) {
case 'boolean':
modifier = XsdBoolean;
break;
case 'number':
if (isFinite(value))
modifier = value % 1 === 0 ? XsdInteger : XsdDouble;
else {
modifier = XsdDouble;
if (!isNaN(value))
value = value > 0 ? 'INF' : '-INF';
}
break;
default:
return '"' + value + '"';
}
}
return '"' + value +
(/^[a-z]+(-[a-z0-9]+)*$/i.test(modifier) ? '"@' + modifier.toLowerCase()
: '"^^' + modifier);
},
// Creates a function that prepends the given IRI to a local name
prefix: function (iri) {
return N3Util.prefixes({ '': iri })('');
prefix: function (iri, factory) {
return N3Util.prefixes({ '': iri }, factory)('');
},
// Creates a function that allows registering and expanding prefixes
prefixes: function (defaultPrefixes) {
prefixes: function (defaultPrefixes, factory) {
// Add all of the default prefixes

@@ -127,2 +47,4 @@ var prefixes = Object.create(null);

processPrefix(prefix, defaultPrefixes[prefix]);
// Set the default factory if none was specified
factory = factory || DataFactory;

@@ -133,10 +55,12 @@ // Registers a new prefix (if an IRI was specified)

// Create a new prefix if an IRI is specified or the prefix doesn't exist
if (iri || !(prefix in prefixes)) {
if (typeof iri === 'string') {
// Create a function that expands the prefix
var cache = Object.create(null);
iri = iri || '';
// Create a function that expands the prefix
prefixes[prefix] = function (localName) {
return cache[localName] || (cache[localName] = iri + localName);
prefixes[prefix] = function (local) {
return cache[local] || (cache[local] = factory.namedNode(iri + local));
};
}
else if (!(prefix in prefixes)) {
throw new Error('Unknown prefix: ' + prefix);
}
return prefixes[prefix];

@@ -143,0 +67,0 @@ }

// **N3Writer** writes N3 documents.
// Matches a literal as represented in memory by the N3 library
var N3LiteralMatcher = /^"([^]*)"(?:\^\^(.+)|@([a-z]+(?:-[a-z0-9]+)*))?$/i;
var namespaces = require('./IRIs'),
DataFactory = require('./N3DataFactory');
// rdf:type predicate (for 'a' abbreviation)
var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
RDF_TYPE = RDF_PREFIX + 'type';
var DEFAULTGRAPH = DataFactory.defaultGraph();
var rdf = namespaces.rdf,
xsd = namespaces.xsd;
// Characters in literals that require escaping

@@ -45,3 +46,3 @@ var escape = /["\\\t\n\r\b\f\u0000-\u0019\ud800-\udbff]/,

if (!(/triple|quad/i).test(options.format)) {
this._graph = '';
this._graph = DEFAULTGRAPH;
this._prefixIRIs = Object.create(null);

@@ -51,3 +52,3 @@ options.prefixes && this.addPrefixes(options.prefixes);

else {
this._writeTriple = this._writeTripleLine;
this._writeQuad = this._writeQuadLine;
}

@@ -59,2 +60,7 @@ }

// ### Whether the current graph is the default graph
get _inDefaultGraph() {
return DEFAULTGRAPH.equals(this._graph);
},
// ### `_write` writes the argument to the output stream

@@ -65,18 +71,17 @@ _write: function (string, callback) {

// ### `_writeTriple` writes the triple to the output stream
_writeTriple: function (subject, predicate, object, graph, done) {
// ### `_writeQuad` writes the quad to the output stream
_writeQuad: function (subject, predicate, object, graph, done) {
try {
// Write the graph's label if it has changed
if (this._graph !== graph) {
if (!graph.equals(this._graph)) {
// Close the previous graph and start the new one
this._write((this._subject === null ? '' : (this._graph ? '\n}\n' : '.\n')) +
(graph ? this._encodeIriOrBlankNode(graph) + ' {\n' : ''));
this._write((this._subject === null ? '' : (this._inDefaultGraph ? '.\n' : '\n}\n')) +
(DEFAULTGRAPH.equals(graph) ? '' : this._encodeIriOrBlank(graph) + ' {\n'));
this._graph = graph;
this._subject = null;
// Don't treat identical blank nodes as repeating graphs
this._graph = graph[0] !== '[' ? graph : ']';
}
// Don't repeat the subject if it's the same
if (this._subject === subject) {
if (subject.equals(this._subject)) {
// Don't repeat the predicate if it's the same
if (this._predicate === predicate)
if (predicate.equals(this._predicate))
this._write(', ' + this._encodeObject(object), done);

@@ -89,6 +94,6 @@ // Same subject, different predicate

}
// Different subject; write the whole triple
// Different subject; write the whole quad
else
this._write((this._subject === null ? '' : '.\n') +
this._encodeSubject(this._subject = subject) + ' ' +
this._encodeIriOrBlank(this._subject = subject) + ' ' +
this._encodePredicate(this._predicate = predicate) + ' ' +

@@ -100,50 +105,50 @@ this._encodeObject(object), done);

// ### `_writeTripleLine` writes the triple or quad to the output stream as a single line
_writeTripleLine: function (subject, predicate, object, graph, done) {
// Write the triple without prefixes
// ### `_writeQuadLine` writes the quad to the output stream as a single line
_writeQuadLine: function (subject, predicate, object, graph, done) {
// Write the quad without prefixes
delete this._prefixMatch;
try { this._write(this.tripleToString(subject, predicate, object, graph), done); }
catch (error) { done && done(error); }
this._write(this.quadToString(subject, predicate, object, graph), done);
},
// ### `tripleToString` serializes a triple or quad as a string
tripleToString: function (subject, predicate, object, graph) {
return this._encodeIriOrBlankNode(subject) + ' ' +
this._encodeIriOrBlankNode(predicate) + ' ' +
// ### `quadToString` serializes a quad as a string
quadToString: function (subject, predicate, object, graph) {
return this._encodeIriOrBlank(subject) + ' ' +
this._encodeIriOrBlank(predicate) + ' ' +
this._encodeObject(object) +
(graph ? ' ' + this._encodeIriOrBlankNode(graph) + '.\n' : '.\n');
(graph && graph.value ? ' ' + this._encodeIriOrBlank(graph) + '.\n' : '.\n');
},
// ### `triplesToString` serializes an array of triples or quads as a string
triplesToString: function (triples) {
return triples.map(function (t) {
return this.tripleToString(t.subject, t.predicate, t.object, t.graph);
// ### `quadsToString` serializes an array of quads as a string
quadsToString: function (quads) {
return quads.map(function (t) {
return this.quadToString(t.subject, t.predicate, t.object, t.graph);
}, this).join('');
},
// ### `_encodeIriOrBlankNode` represents an IRI or blank node
_encodeIriOrBlankNode: function (entity) {
// ### `_encodeIriOrBlank` represents an IRI or blank node
_encodeIriOrBlank: function (entity) {
// A blank node or list is represented as-is
var firstChar = entity[0];
if (firstChar === '[' || firstChar === '(' || firstChar === '_' && entity[1] === ':')
return entity;
if (entity.termType !== 'NamedNode')
return 'id' in entity ? entity.id : '_:' + entity.value;
// Escape special characters
if (escape.test(entity))
entity = entity.replace(escapeAll, characterReplacer);
var iri = entity.value;
if (escape.test(iri))
iri = iri.replace(escapeAll, characterReplacer);
// Try to represent the IRI as prefixed name
var prefixMatch = this._prefixRegex.exec(entity);
return !prefixMatch ? '<' + entity + '>' :
(!prefixMatch[1] ? entity : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]);
var prefixMatch = this._prefixRegex.exec(iri);
return !prefixMatch ? '<' + iri + '>' :
(!prefixMatch[1] ? iri : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]);
},
// ### `_encodeLiteral` represents a literal
_encodeLiteral: function (value, type, language) {
_encodeLiteral: function (literal) {
// Escape special characters
var value = literal.value;
if (escape.test(value))
value = value.replace(escapeAll, characterReplacer);
// Write the literal, possibly with type or language
if (language)
return '"' + value + '"@' + language;
else if (type)
return '"' + value + '"^^' + this._encodeIriOrBlankNode(type);
if (literal.language)
return '"' + value + '"@' + literal.language;
else if (literal.datatype.value !== xsd.string)
return '"' + value + '"^^' + this._encodeIriOrBlank(literal.datatype);
else

@@ -153,17 +158,5 @@ return '"' + value + '"';

// ### `_encodeSubject` represents a subject
_encodeSubject: function (subject) {
if (subject[0] === '"')
throw new Error('A literal as subject is not allowed: ' + subject);
// Don't treat identical blank nodes as repeating subjects
if (subject[0] === '[')
this._subject = ']';
return this._encodeIriOrBlankNode(subject);
},
// ### `_encodePredicate` represents a predicate
_encodePredicate: function (predicate) {
if (predicate[0] === '"')
throw new Error('A literal as predicate is not allowed: ' + predicate);
return predicate === RDF_TYPE ? 'a' : this._encodeIriOrBlankNode(predicate);
return predicate.value === rdf.type ? 'a' : this._encodeIriOrBlank(predicate);
},

@@ -173,9 +166,3 @@

_encodeObject: function (object) {
// Represent an IRI or blank node
if (object[0] !== '"')
return this._encodeIriOrBlankNode(object);
// Represent a literal
var match = N3LiteralMatcher.exec(object);
if (!match) throw new Error('Invalid literal: ' + object);
return this._encodeLiteral(match[1], match[2], match[3]);
return object.termType === 'Literal' ? this._encodeLiteral(object) : this._encodeIriOrBlank(object);
},

@@ -188,20 +175,19 @@

// ### `addTriple` adds the triple to the output stream
addTriple: function (subject, predicate, object, graph, done) {
// The triple was given as a triple object, so shift parameters
// ### `addQuad` adds the quad to the output stream
addQuad: function (subject, predicate, object, graph, done) {
// The quad was given as an object, so shift parameters
if (object === undefined)
this._writeTriple(subject.subject, subject.predicate, subject.object,
subject.graph || '', predicate);
this._writeQuad(subject.subject, subject.predicate, subject.object, subject.graph, predicate);
// The optional `graph` parameter was not provided
else if (typeof graph !== 'string')
this._writeTriple(subject, predicate, object, '', graph);
else if (typeof graph === 'function')
this._writeQuad(subject, predicate, object, DEFAULTGRAPH, graph);
// The `graph` parameter was provided
else
this._writeTriple(subject, predicate, object, graph, done);
this._writeQuad(subject, predicate, object, graph || DEFAULTGRAPH, done);
},
// ### `addTriples` adds the triples to the output stream
addTriples: function (triples) {
for (var i = 0; i < triples.length; i++)
this.addTriple(triples[i]);
// ### `addQuads` adds the quads to the output stream
addQuads: function (quads) {
for (var i = 0; i < quads.length; i++)
this.addQuad(quads[i]);
},

@@ -223,8 +209,10 @@

var iri = prefixes[prefix];
if (typeof iri !== 'string')
iri = iri.value;
if (/[#\/]$/.test(iri) && prefixIRIs[iri] !== (prefix += ':')) {
hasPrefixes = true;
prefixIRIs[iri] = prefix;
// Finish a possible pending triple
// Finish a possible pending quad
if (this._subject !== null) {
this._write(this._graph ? '\n}\n' : '.\n');
this._write(this._inDefaultGraph ? '.\n' : '\n}\n');
this._subject = null, this._graph = '';

@@ -257,4 +245,4 @@ }

children = [];
// Blank node passed as blank("predicate", "object")
else if (typeof predicate === 'string')
// Blank node passed as blank(Term("predicate"), Term("object"))
else if (predicate.termType)
children = [{ predicate: predicate, object: object }];

@@ -268,9 +256,9 @@ // Blank node passed as blank({ predicate: predicate, object: object })

case 0:
return '[]';
return new SerializedTerm('[]');
// Generate a non-nested one-triple blank node
case 1:
child = children[0];
if (child.object[0] !== '[')
return '[ ' + this._encodePredicate(child.predicate) + ' ' +
this._encodeObject(child.object) + ' ]';
if (!(child.object instanceof SerializedTerm))
return new SerializedTerm('[ ' + this._encodePredicate(child.predicate) + ' ' +
this._encodeObject(child.object) + ' ]');
// Generate a multi-triple or nested blank node

@@ -283,3 +271,3 @@ default:

// Write only the object is the predicate is the same as the previous
if (child.predicate === predicate)
if (child.predicate.equals(predicate))
contents += ', ' + this._encodeObject(child.object);

@@ -294,3 +282,3 @@ // Otherwise, write the predicate and the object

}
return contents + '\n]';
return new SerializedTerm(contents + '\n]');
}

@@ -304,3 +292,3 @@ },

contents[i] = this._encodeObject(elements[i]);
return '(' + contents.join(' ') + ')';
return new SerializedTerm('(' + contents.join(' ') + ')');
},

@@ -313,5 +301,5 @@

end: function (done) {
// Finish a possible pending triple
// Finish a possible pending quad
if (this._subject !== null) {
this._write(this._graph ? '\n}\n' : '.\n');
this._write(this._inDefaultGraph ? '.\n' : '\n}\n');
this._subject = null;

@@ -352,3 +340,13 @@ }

// ## Placeholder class to represent already pretty-printed terms
function SerializedTerm(value) {
this.id = value;
}
DataFactory.internal.Term.subclass(SerializedTerm);
// Pretty-printed nodes are not equal to any other node
// (e.g., [] does not equal [])
SerializedTerm.prototype.equals = function () { return false; };
// ## Exports
module.exports = N3Writer;
# License
The MIT License (MIT)
Copyright ©2012–2016 Ruben Verborgh
Copyright ©2012–2018 Ruben Verborgh

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

@@ -7,2 +7,3 @@ // Replace local require by a lazy loader

var exports = module.exports = {
DataFactory: require('./lib/N3DataFactory'),
Lexer: require('./lib/N3Lexer'),

@@ -9,0 +10,0 @@ Parser: require('./lib/N3Parser'),

{
"name": "n3",
"version": "0.11.3",
"version": "1.0.0-alpha",
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",

@@ -24,3 +24,2 @@ "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",

"async": "^2.0.1",
"browserify": "^16.1.0",
"chai": "^4.0.2",

@@ -30,3 +29,2 @@ "chai-things": "^0.2.0",

"coveralls": "^3.0.0",
"cross-spawn": "^6.0.4",
"docco": "^0.7.0",

@@ -37,4 +35,3 @@ "eslint": "^4.1.1",

"pre-commit": "^1.2.2",
"request": "^2.74.0",
"uglify-js": "^3.0.24"
"request": "^2.74.0"
},

@@ -44,3 +41,2 @@ "scripts": {

"lint": "eslint lib perf test spec",
"browser": "node browser/build-browser-versions",
"coveralls": "nyc --reporter=text-lcov mocha | coveralls",

@@ -53,19 +49,7 @@ "spec": "node spec/turtle-spec && node spec/trig-spec && node spec/ntriples-spec && node spec/nquads-spec",

"type": "git",
"url": "https://github.com/RubenVerborgh/N3.js.git"
"url": "https://github.com/rdfjs/N3.js.git"
},
"bugs": {
"url": "https://github.com/RubenVerborgh/N3.js/issues"
"url": "https://github.com/rdfjs/N3.js/issues"
},
"testling": {
"files": "test/*.js",
"harness": "mocha",
"browsers": [
"ie/9..latest",
"firefox/24..latest",
"chrome/29..latest",
"safari/6..latest",
"iphone/6..latest",
"ipad/6..latest"
]
},
"pre-commit": [

@@ -72,0 +56,0 @@ "lint",

# Lightning fast, asynchronous, streaming RDF for JavaScript
[![Build Status](https://travis-ci.org/RubenVerborgh/N3.js.svg?branch=master)](https://travis-ci.org/RubenVerborgh/N3.js)
[![Build status](https://ci.appveyor.com/api/projects/status/ede443yeiq3syhyg/branch/master?svg=true)](https://ci.appveyor.com/project/RubenVerborgh/n3-js/branch/master)
[![Coverage Status](https://coveralls.io/repos/github/RubenVerborgh/N3.js/badge.svg)](https://coveralls.io/github/RubenVerborgh/N3.js)
[![Build Status](https://travis-ci.org/rdfjs/N3.js.svg?branch=master)](https://travis-ci.org/rdfjs/N3.js)
[![Coverage Status](https://coveralls.io/repos/github/rdfjs/N3.js/badge.svg)](https://coveralls.io/github/rdfjs/N3.js)
[![npm version](https://badge.fury.io/js/n3.svg)](https://www.npmjs.com/package/n3)
[![DOI](https://zenodo.org/badge/3058202.svg)](https://zenodo.org/badge/latestdoi/3058202)
The N3.js library lets you handle [RDF](http://www.w3.org/TR/rdf-primer/) in JavaScript easily, in [Node.js](http://nodejs.org/) and the browser.
The N3.js library is an implementation of the [RDF.js low-level specification](http://rdf.js.org/) that lets you handle [RDF](https://www.w3.org/TR/rdf-primer/) in JavaScript easily.
It offers:
- [**Parsing**](#parsing) triples/quads from
[Turtle](http://www.w3.org/TR/turtle/),
[TriG](http://www.w3.org/TR/trig/),
[N-Triples](http://www.w3.org/TR/n-triples/),
[N-Quads](http://www.w3.org/TR/n-quads/),
[Turtle](https://www.w3.org/TR/turtle/),
[TriG](https://www.w3.org/TR/trig/),
[N-Triples](https://www.w3.org/TR/n-triples/),
[N-Quads](https://www.w3.org/TR/n-quads/),
and [Notation3 (N3)](https://www.w3.org/TeamSubmission/n3/)
- [**Writing**](#writing) triples/quads to
[Turtle](http://www.w3.org/TR/turtle/),
[TriG](http://www.w3.org/TR/trig/),
[N-Triples](http://www.w3.org/TR/n-triples/),
and [N-Quads](http://www.w3.org/TR/n-quads/)
[Turtle](https://www.w3.org/TR/turtle/),
[TriG](https://www.w3.org/TR/trig/),
[N-Triples](https://www.w3.org/TR/n-triples/),
and [N-Quads](https://www.w3.org/TR/n-quads/)
- [**Storage**](#storing) of triples/quads in memory

@@ -27,3 +26,3 @@

- **streaming** – streams are parsed as data comes in, so you can parse files larger than memory
- **fast** – by far the [fastest parser in JavaScript](https://github.com/RubenVerborgh/N3.js/tree/master/perf)
- **fast** – by far the [fastest spec-compatible parser in JavaScript](https://github.com/rdfjs/N3.js/tree/master/perf)

@@ -33,101 +32,57 @@ ## Installation

``` bash
```Bash
$ npm install n3
```
``` js
var N3 = require('n3');
```JavaScript
const N3 = require('n3');
```
N3.js seamlessly works in browsers. Generate a browser version as follows:
N3.js seamlessly works in browsers via [webpack](https://webpack.js.org/) or [browserify](http://browserify.org/).
``` bash
$ cd N3.js
$ npm install
$ npm run browser
```
## Creating triples/quads
N3.js follows the [RDF.js low-level specification](http://rdf.js.org/).
``` html
<script src="n3-browser.min.js"></script>
```
`N3.DataFactory` will give you the [factory](http://rdf.js.org/#datafactory-interface) functions to create triples and quads:
In addition, N3.js is fully compatible with [browserify](http://browserify.org/),
so you can write code for Node.js and deploy it to browsers.
## Triple representation
For maximum performance and ease of use,
triples are simple objects with string properties.
**URLs, URIs and IRIs are simple strings.** For example, parsing this RDF document:
``` Turtle
@prefix c: <http://example.org/cartoons#>.
c:Tom a c:Cat.
```JavaScript
const { DataFactory } = N3;
const { namedNode, literal, defaultGraph, quad } = DataFactory;
const myQuad = quad(
namedNode('https://ruben.verborgh.org/profile/#me'),
namedNode('http://xmlns.com/foaf/0.1/givenName'),
literal('Ruben', 'en'),
defaultGraph(),
);
console.log(myQuad.subject.value); // https://ruben.verborgh.org/profile/#me
console.log(myQuad.object.value); // Ruben
console.log(myQuad.object.datatype.value); // http://www.w3.org/1999/02/22-rdf-syntax-ns#langString
console.log(myQuad.object.language); // en
```
results in this JavaScript object:
``` js
{
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
object: 'http://example.org/cartoons#Cat'
}
```
**Literals are represented as double quoted strings.** For example, parsing this RDF document:
``` Turtle
c:Tom c:name "Tom".
```
results in this JavaScript object:
``` js
{
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"'
}
```
In the rest of this document, we will treat “triples” and “quads” equally:
we assume that a quad is simply a triple in a named or default graph.
This allows you to create and compare literals fast and easily:
``` js
triple.object === 'http://example.org/cartoons#Cat'
triple.object === '"Tom"'
```
For literals with a language or type, add a marker (`@` or `^^`) and the corresponding value as-is:
``` js
'"Tom"@en-gb' // lowercase language
'"1"^^http://www.w3.org/2001/XMLSchema#integer' // no angular brackets <>
```
An optional fourth element signals the graph to which a triple belongs:
``` js
{
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"',
graph: 'http://example.org/mycartoon'
}
```
The N3.js [Utility](#utility) (`N3.Util`) can help you with these representations.
## Parsing
### From an RDF document to triples
### From an RDF document to quads
`N3.Parser` transforms Turtle, TriG, N-Triples or N-Quads document into triples through a callback:
``` js
var parser = N3.Parser();
parser.parse('@prefix c: <http://example.org/cartoons#>.\n' +
'c:Tom a c:Cat.\n' +
'c:Jerry a c:Mouse;\n' +
' c:smarterThan c:Tom.',
function (error, triple, prefixes) {
if (triple)
console.log(triple.subject, triple.predicate, triple.object, '.');
else
console.log("# That's all, folks!", prefixes)
});
`N3.Parser` transforms Turtle, TriG, N-Triples, or N-Quads document into quads through a callback:
```JavaScript
const parser = new N3.Parser();
parser.parse(
`PREFIX c: <http://example.org/cartoons#>
c:Tom a c:Cat.
c:Jerry a c:Mouse;
c:smarterThan c:Tom.`,
(error, quad, prefixes) => {
if (quad)
console.log(quad);
else
console.log("# That's all, folks!", prefixes);
});
```
The callback's first argument is an error value, the second is a triple.
If there are no more triples,
the callback is invoked one last time with `null` for `triple`
The callback's first argument is an optional error value, the second is a quad.
If there are no more quads,
the callback is invoked one last time with `null` for `quad`
and a hash of prefixes as third argument.

@@ -139,9 +94,9 @@ <br>

By default, `N3.Parser` parses a permissive superset of Turtle, TriG, N-Triples and N-Quads.
By default, `N3.Parser` parses a permissive superset of Turtle, TriG, N-Triples, and N-Quads.
<br>
For strict compatibility with any of those languages, pass a `format` argument upon creation:
``` js
var parser1 = N3.Parser({ format: 'N-Triples' });
var parser2 = N3.Parser({ format: 'application/trig' });
```JavaScript
const parser1 = N3.Parser({ format: 'N-Triples' });
const parser2 = N3.Parser({ format: 'application/trig' });
```

@@ -151,29 +106,26 @@

``` js
var parser3 = N3.Parser({ format: 'N3' });
var parser4 = N3.Parser({ format: 'Notation3' });
var parser5 = N3.Parser({ format: 'text/n3' });
```JavaScript
const parser3 = N3.Parser({ format: 'N3' });
const parser4 = N3.Parser({ format: 'Notation3' });
const parser5 = N3.Parser({ format: 'text/n3' });
```
### From an RDF stream to triples
### From an RDF stream to quads
`N3.Parser` can parse [Node.js streams](http://nodejs.org/api/stream.html) as they grow,
returning triples as soon as they're ready.
<br>
This behavior sets N3.js apart from most other libraries.
returning quads as soon as they're ready.
``` js
var parser = N3.Parser(),
rdfStream = fs.createReadStream('cartoons.ttl');
```JavaScript
const parser = N3.Parser(),
rdfStream = fs.createReadStream('cartoons.ttl');
parser.parse(rdfStream, console.log);
```
In addition, `N3.StreamParser` offers a [Node.js stream](http://nodejs.org/api/stream.html) implementation,
so you can transform RDF streams and pipe them to anywhere.
`N3.StreamParser` is a [Node.js stream](http://nodejs.org/api/stream.html) and [RDF.js Sink](http://rdf.js.org/#sink-interface) implementation.
This solution is ideal if your consumer is slower,
since source data is only read when the consumer is ready.
``` js
var streamParser = N3.StreamParser(),
rdfStream = fs.createReadStream('cartoons.ttl');
```JavaScript
const streamParser = N3.StreamParser(),
rdfStream = fs.createReadStream('cartoons.ttl');
rdfStream.pipe(streamParser);

@@ -183,5 +135,5 @@ streamParser.pipe(new SlowConsumer());

function SlowConsumer() {
var writer = new require('stream').Writable({ objectMode: true });
writer._write = function (triple, encoding, done) {
console.log(triple);
const writer = new require('stream').Writable({ objectMode: true });
writer._write = (quad, encoding, done) => {
console.log(quad);
setTimeout(done, 1000);

@@ -193,58 +145,62 @@ };

A dedicated `prefix` event signals every prefix with `prefix` and `iri` arguments.
A dedicated `prefix` event signals every prefix with `prefix` and `term` arguments.
## Writing
### From triples to a string
### From quads to a string
`N3.Writer` serializes triples as an RDF document.
Write triples through `addTriple`.
`N3.Writer` serializes quads as an RDF document.
Write quads through `addQuad`.
``` js
var writer = N3.Writer({ prefixes: { c: 'http://example.org/cartoons#' } });
writer.addTriple('http://example.org/cartoons#Tom',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'http://example.org/cartoons#Cat');
writer.addTriple({
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"'
});
writer.end(function (error, result) { console.log(result); });
```JavaScript
const writer = N3.Writer({ prefixes: { c: 'http://example.org/cartoons#' } });
writer.addQuad(
namedNode('http://example.org/cartoons#Tom'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.org/cartoons#Cat')
);
writer.addQuad(quad(
namedNode('http://example.org/cartoons#Tom'),
namedNode('http://example.org/cartoons#name'),
literal('Tom')
));
writer.end((error, result) => console.log(result));
```
By default, `N3.Writer` writes Turtle (or TriG for triples with a `graph` property).
By default, `N3.Writer` writes Turtle (or TriG if some quads are in a named graph).
<br>
To write N-Triples (or N-Quads) instead, pass a `format` argument upon creation:
``` js
var writer1 = N3.Writer({ format: 'N-Triples' });
var writer2 = N3.Writer({ format: 'application/trig' });
```JavaScript
const writer1 = N3.Writer({ format: 'N-Triples' });
const writer2 = N3.Writer({ format: 'application/trig' });
```
### From triples to an RDF stream
### From quads to an RDF stream
`N3.Writer` can also write triples to a Node.js stream.
`N3.Writer` can also write quads to a Node.js stream.
``` js
var writer = N3.Writer(process.stdout, { end: false, prefixes: { c: 'http://example.org/cartoons#' } });
writer.addTriple('http://example.org/cartoons#Tom',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'http://example.org/cartoons#Cat');
writer.addTriple({
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"'
});
```JavaScript
const writer = N3.Writer(process.stdout, { end: false, prefixes: { c: 'http://example.org/cartoons#' } });
writer.addQuad(
namedNode('http://example.org/cartoons#Tom'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.org/cartoons#Cat')
);
writer.addQuad(quad(
namedNode('http://example.org/cartoons#Tom'),
namedNode('http://example.org/cartoons#name'),
literal('Tom')
));
writer.end();
```
### From a triple stream to an RDF stream
### From a quad stream to an RDF stream
`N3.StreamWriter` is a writer implementation as a Node.js stream.
`N3.StreamWriter` is a [Node.js stream](http://nodejs.org/api/stream.html) and [RDF.js Sink](http://rdf.js.org/#sink-interface) implementation.
``` js
var streamParser = new N3.StreamParser(),
inputStream = fs.createReadStream('cartoons.ttl'),
streamWriter = new N3.StreamWriter({ prefixes: { c: 'http://example.org/cartoons#' } });
```JavaScript
const streamParser = new N3.StreamParser(),
inputStream = fs.createReadStream('cartoons.ttl'),
streamWriter = new N3.StreamWriter({ prefixes: { c: 'http://example.org/cartoons#' } });
inputStream.pipe(streamParser);

@@ -262,31 +218,34 @@ streamParser.pipe(streamWriter);

The `blank` and `list` functions allow you to create them manually instead:
```js
var writer = N3.Writer({ prefixes: { c: 'http://example.org/cartoons#',
foaf: 'http://xmlns.com/foaf/0.1/' } });
writer.addTriple(writer.blank('http://xmlns.com/foaf/0.1/givenName', '"Tom"@en'),
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
'http://example.org/cartoons#Cat');
writer.addTriple('http://example.org/cartoons#Jerry',
'http://xmlns.com/foaf/0.1/knows',
writer.blank([{
predicate: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
object: 'http://example.org/cartoons#Cat'
},{
predicate: 'http://xmlns.com/foaf/0.1/givenName',
object: '"Tom"@en',
}]));
writer.addTriple('http://example.org/cartoons#Mammy',
'http://example.org/cartoons#hasPets',
writer.list([
'http://example.org/cartoons#Tom',
'http://example.org/cartoons#Jerry'
]));
writer.end(function (error, result) { console.log(result); });
```JavaScript
const writer = N3.Writer({ prefixes: { c: 'http://example.org/cartoons#',
foaf: 'http://xmlns.com/foaf/0.1/' } });
writer.addQuad(
writer.blank(
namedNode('http://xmlns.com/foaf/0.1/givenName'),
literal('Tom', 'en')),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.org/cartoons#Cat')
);
writer.addQuad(quad(
namedNode('http://example.org/cartoons#Jerry'),
namedNode('http://xmlns.com/foaf/0.1/knows'),
writer.blank([{
predicate: namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
object: namedNode('http://example.org/cartoons#Cat'),
},{
predicate: namedNode('http://xmlns.com/foaf/0.1/givenName'),
object: literal('Tom', 'en'),
}])
));
writer.addQuad(
namedNode('http://example.org/cartoons#Mammy'),
namedNode('http://example.org/cartoons#hasPets'),
writer.list([
namedNode('http://example.org/cartoons#Tom'),
namedNode('http://example.org/cartoons#Jerry'),
])
);
writer.end((error, result) => console.log(result));
```
Be careful to use the output of `blank` and `list`
**only once** and **only as argument to `addTriple`** of the same writer,
as return values of these functions are unspecified.
## Storing

@@ -300,111 +259,56 @@

``` js
var store = N3.Store();
store.addTriple('http://ex.org/Pluto', 'http://ex.org/type', 'http://ex.org/Dog');
store.addTriple('http://ex.org/Mickey', 'http://ex.org/type', 'http://ex.org/Mouse');
```JavaScript
const store = N3.Store();
store.addQuad(
namedNode('http://ex.org/Pluto'),
namedNode('http://ex.org/type'),
namedNode('http://ex.org/Dog')
);
store.addQuad(
namedNode('http://ex.org/Mickey'),
namedNode('http://ex.org/type'),
namedNode('http://ex.org/Mouse')
);
var mickey = store.getTriples('http://ex.org/Mickey', null, null)[0];
console.log(mickey.subject, mickey.predicate, mickey.object, '.');
const mickey = store.getQuads(namedNode('http://ex.org/Mickey'), null, null)[0];
console.log(mickey);
```
### Addition and deletion of triples/quads
### Addition and deletion of quads
The store provides the following manipulation methods
([documentation](http://rubenverborgh.github.io/N3.js/docs/N3Store.html)):
- `addTriple` to insert one triple/quad
- `addTriples` to insert an array of triples/quads
- `addPrefix` to register a prefix (facilitating lookup)
- `addPrefixes` to register an array of prefixes
- `removeTriple` to remove one triple/quad
- `removeTriples` to remove an array of triples/quads
([documentation](http://rdfjs.github.io/N3.js/docs/N3Store.html)):
- `addQuad` to insert one quad
- `addQuads` to insert an array of quads
- `removeQuad` to remove one quad
- `removeQuads` to remove an array of quads
- `createBlankNode` returns an unused blank node identifier
### Searching triples/quads or entities
### Searching quads or entities
The store provides the following search methods
([documentation](http://rubenverborgh.github.io/N3.js/docs/N3Store.html)):
- `getTriples` returns an array of triples/quads matching the given pattern
- `countTriples` counts the number of triples/quads matching the given pattern
- `forEach` executes a callback on all matching triples/quads
- `every` returns whether a callback on matching triples/quads always returns true
- `some` returns whether a callback on matching triples/quads returns true at least once
- `getSubjects` returns an array of unique subjects occurring in matching triples
- `forSubjects` executes a callback on unique subjects occurring in matching triples
- `getPredicates` returns an array of unique predicates occurring in matching triple
- `forPredicates` executes a callback on unique predicates occurring in matching triples
- `getObjects` returns an array of unique objects occurring in matching triple
- `forObjects` executes a callback on unique objects occurring in matching triples
- `getGraphs` returns an array of unique graphs occurring in matching triple
- `forGraphs` executes a callback on unique graphs occurring in matching triples
([documentation](http://rdfjs.github.io/N3.js/docs/N3Store.html)):
- `getQuads` returns an array of quads matching the given pattern
- `countQuads` counts the number of quads matching the given pattern
- `forEach` executes a callback on all matching quads
- `every` returns whether a callback on matching quads always returns true
- `some` returns whether a callback on matching quads returns true at least once
- `getSubjects` returns an array of unique subjects occurring in matching quads
- `forSubjects` executes a callback on unique subjects occurring in matching quads
- `getPredicates` returns an array of unique predicates occurring in matching quad
- `forPredicates` executes a callback on unique predicates occurring in matching quads
- `getObjects` returns an array of unique objects occurring in matching quad
- `forObjects` executes a callback on unique objects occurring in matching quads
- `getGraphs` returns an array of unique graphs occurring in matching quad
- `forGraphs` executes a callback on unique graphs occurring in matching quads
All of the above methods also have a variant with the `byIRI` suffix
(e.g., `getTriplesByIRI`),
which skips prefix expansion and is thus faster.
## Utility
`N3.Util` offers helpers for IRI and literal representations.
<br>
As IRIs are most common, they are represented as simple strings:
``` js
var N3Util = N3.Util;
N3Util.isIRI('http://example.org/cartoons#Mickey'); // true
```
**Literals** are represented as double quoted strings:
``` js
N3Util.isLiteral('"Mickey Mouse"'); // true
N3Util.getLiteralValue('"Mickey Mouse"'); // 'Mickey Mouse'
N3Util.isLiteral('"Mickey Mouse"@en'); // true
N3Util.getLiteralLanguage('"Mickey Mouse"@en'); // 'en'
N3Util.isLiteral('"3"^^http://www.w3.org/2001/XMLSchema#integer'); // true
N3Util.getLiteralType('"3"^^http://www.w3.org/2001/XMLSchema#integer'); // 'http://www.w3.org/2001/XMLSchema#integer'
N3Util.isLiteral('"http://example.org/"'); // true
N3Util.getLiteralValue('"http://example.org/"'); // 'http://example.org/'
```
Note the difference between `'http://example.org/'` (IRI) and `'"http://example.org/"'` (literal).
<br>
Also note that the double quoted literals are _not_ raw Turtle/TriG syntax:
``` js
N3Util.isLiteral('"This word is "quoted"!"'); // true
N3Util.isLiteral('"3"^^http://www.w3.org/2001/XMLSchema#integer'); // true
```
The above string represents the string _This word is "quoted"!_,
even though the correct Turtle/TriG syntax for that is `"This word is \"quoted\"!"`
N3.js thus always parses literals, but adds quotes to differentiate from IRIs:
``` js
new N3.Parser().parse('<a> <b> "This word is \\"quoted\\"!".', console.log);
// { subject: 'a', predicate: 'b', object: '"This word is "quoted"!"' }
```
Literals can be created with `createLiteral`:
``` js
N3Util.createLiteral('My text', 'en-gb');
N3Util.createLiteral('123', 'http://www.w3.org/2001/XMLSchema#integer');
N3Util.createLiteral(123);
N3Util.createLiteral(false);
```
**Blank nodes** start with `_:`, and can be tested for as follows:
``` js
N3Util.isBlank('_:b1'); // true
N3Util.isIRI('_:b1'); // false
N3Util.isLiteral('_:b1'); // false
```
**Prefixed names** can be tested and expanded:
``` js
var prefixes = { rdfs: 'http://www.w3.org/2000/01/rdf-schema#' };
N3Util.isPrefixedName('rdfs:label'); // true;
N3Util.expandPrefixedName('rdfs:label', prefixes); // http://www.w3.org/2000/01/rdf-schema#label
```
## Compatibility
### Specifications
### Format specifications
The N3.js parser and writer is fully compatible with the following W3C specifications:
- [RDF 1.1 Turtle](http://www.w3.org/TR/turtle/)
– [EARL report](https://raw.githubusercontent.com/RubenVerborgh/N3.js/earl/n3js-earl-report-turtle.ttl)
- [RDF 1.1 TriG](http://www.w3.org/TR/trig/)
– [EARL report](https://raw.githubusercontent.com/RubenVerborgh/N3.js/earl/n3js-earl-report-trig.ttl)
- [RDF 1.1 N-Triples](http://www.w3.org/TR/n-triples/)
– [EARL report](https://raw.githubusercontent.com/RubenVerborgh/N3.js/earl/n3js-earl-report-ntriples.ttl)
- [RDF 1.1 N-Quads](http://www.w3.org/TR/n-quads/)
– [EARL report](https://raw.githubusercontent.com/RubenVerborgh/N3.js/earl/n3js-earl-report-nquads.ttl)
- [RDF 1.1 Turtle](https://www.w3.org/TR/turtle/)
– [EARL report](https://raw.githubusercontent.com/rdfjs/N3.js/earl/n3js-earl-report-turtle.ttl)
- [RDF 1.1 TriG](https://www.w3.org/TR/trig/)
– [EARL report](https://raw.githubusercontent.com/rdfjs/N3.js/earl/n3js-earl-report-trig.ttl)
- [RDF 1.1 N-Triples](https://www.w3.org/TR/n-triples/)
– [EARL report](https://raw.githubusercontent.com/rdfjs/N3.js/earl/n3js-earl-report-ntriples.ttl)
- [RDF 1.1 N-Quads](https://www.w3.org/TR/n-quads/)
– [EARL report](https://raw.githubusercontent.com/rdfjs/N3.js/earl/n3js-earl-report-nquads.ttl)

@@ -416,7 +320,34 @@ In addition, the N3.js parser also supports [Notation3 (N3)](https://www.w3.org/TeamSubmission/n3/) (no official specification yet).

## License, status and contributions
The N3.js library is copyrighted by [Ruben Verborgh](http://ruben.verborgh.org/)
and released under the [MIT License](https://github.com/RubenVerborgh/N3.js/blob/master/LICENSE.md).
### Interface specifications
The N3.js submodules are compatible with the following [RDF.js](http://rdf.js.org) interfaces:
- `N3.DataFactory` implements
[`DataFactory`](http://rdf.js.org/#datafactory-interface)
- the terms it creates implement [`Term`](http://rdf.js.org/#term-interface)
and one of
[`NamedNode`](http://rdf.js.org/#namednode-interface),
[`BlankNode`](http://rdf.js.org/#blanknode-interface),
[`Literal`](http://rdf.js.org/#litereal-interface),
[`Variable`](http://rdf.js.org/#variable-interface),
[`DefaultGraph`](http://rdf.js.org/#defaultgraph-interface)
- the triples/quads it creates implement
[`Triple`](http://rdf.js.org/#triple-interface)
and
[`Quad`](http://rdf.js.org/#quad-interface)
- `N3.StreamParser` implements
[`Stream`](http://rdf.js.org/#stream-interface)
and
[`Sink`](http://rdf.js.org/#sink-interface)
- `N3.StreamWriter` implements
[`Stream`](http://rdf.js.org/#stream-interface)
and
[`Sink`](http://rdf.js.org/#sink-interface)
- `N3.Store` implements
[`Sink`](http://rdf.js.org/#stream-interface)
## License and contributions
The N3.js library is copyrighted by [Ruben Verborgh](https://ruben.verborgh.org/)
and released under the [MIT License](https://github.com/rdfjs/N3.js/blob/master/LICENSE.md).
Contributions are welcome, and bug reports or pull requests are always helpful.
If you plan to implement a larger feature, it's best to contact me first.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc