From c599f50579b3c9569bc396c0eedc3218a02ae9f8 Mon Sep 17 00:00:00 2001 From: Raphael Cazenave-Leveque Date: Tue, 17 Feb 2015 19:24:25 +0100 Subject: [PATCH 1/2] experimental --- bower.json | 3 +-- package.json | 3 ++- public/js/main.js | 55 ++++++++++++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/bower.json b/bower.json index 19078c7..24e755d 100644 --- a/bower.json +++ b/bower.json @@ -16,7 +16,6 @@ ], "dependencies": { "requirejs": "~2.1.16", - "rdf-rest-js": "~0.9.1", - "jsonld": "~0.3.20" + "rdfrestjs": "0.9.3" } } diff --git a/package.json b/package.json index 94c1d2b..bec9ccb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "dependencies": { "express": "~4.11.2", "mongoose": "~3.8.22", - "body-parser": "~1.11.0" + "body-parser": "~1.11.0", + "rdfrest": "0.9.3" }, "repository": { "type": "git", diff --git a/public/js/main.js b/public/js/main.js index e20f079..33caa89 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,32 +1,43 @@ /*eslint-env amd, browser*/ -/*eslint no-console:0*/ require.config({ paths: { - jsonld: "../components/jsonld/js/jsonld" + rdfrestjs: "../components/rdfrestjs/browserified/rdfrest-bundle" } }); -define(["jsonld"], function(jsonld) { +define(["rdfrestjs"], function(rdfrestjs) { "use strict"; - var doc = { - "http://schema.org/name": "Manu Sporny", - "http://schema.org/url": {"@id": "http://manu.sporny.org/"}, - "http://schema.org/image": {"@id": "http://manu.sporny.org/images/manu.png"} - }; - var context = { - "name": "http://schema.org/name", - "homepage": {"@id": "http://schema.org/url", "@type": "@id"}, - "image": {"@id": "http://schema.org/image", "@type": "@id"} - }; - - // compact a document according to a particular context - // see: http://json-ld.org/spec/latest/json-ld/#compacted-document-form - jsonld.compact(doc, context, function(err, compacted) { - var para = document.createElement("p"); - var node = document.createTextNode(JSON.stringify(compacted, null, 2)); - para.appendChild(node); - document.body.appendChild(para); + var getCore = rdfrestjs.coreFactory.getCore; + var iri = rdfrestjs.rdfNode.iri; + var namespace = rdfrestjs.rdfNode.namespace; + var nt = rdfrestjs.serializerNTriples.nt; + + var me = iri("http://champin.net"); + var ns = namespace("http://ex.co/vocab#"); + var ressource = getCore(me); + + ressource.getState().then(function(g) { + + // 'cause we cannot use console.log as a function in a browser + //noinspection Eslint + return nt(g, console.info.bind(console)); + + }).then(function() { + + // then we edit the graph + return ressource.edit(function(g) { + return g.addTriple(me, ns("type"), ns("Person")); + }); + }).then(function() { + return ressource.edit(function(g2) { + return g2.addTriple(me, ns("label"), "Pierre-Antoine Champin"); + }); + }).then(function(g) { + //noinspection Eslint + console.log("----\n"); + //noinspection Eslint + return nt(g, console.info.bind(console)); }); -}); \ No newline at end of file +}); From e77a205d09c293471e9436c2dade6c18e6b12ae3 Mon Sep 17 00:00:00 2001 From: Raphael Cazenave-Leveque Date: Thu, 5 Mar 2015 17:45:20 +0100 Subject: [PATCH 2/2] fix the index2.html/main.js example --- bower.json | 2 +- public/js/main.js | 13 + public/js/rdfrestbundle.js | 18986 ----------------------------------- 3 files changed, 14 insertions(+), 18987 deletions(-) delete mode 100644 public/js/rdfrestbundle.js diff --git a/bower.json b/bower.json index 24e755d..3cd1e31 100644 --- a/bower.json +++ b/bower.json @@ -16,6 +16,6 @@ ], "dependencies": { "requirejs": "~2.1.16", - "rdfrestjs": "0.9.3" + "rdfrestjs": "1.0.0" } } diff --git a/public/js/main.js b/public/js/main.js index 33caa89..d33e8c8 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -14,6 +14,19 @@ define(["rdfrestjs"], function(rdfrestjs) { var namespace = rdfrestjs.rdfNode.namespace; var nt = rdfrestjs.serializerNTriples.nt; + // inform the Core factory of a ressource + var BasicCore = rdfrestjs.coreBasic.BasicCore; + var graph = rdfrestjs.graph.graph; + var makeIri = rdfrestjs.rdfNode.iri; + rdfrestjs.coreFactory.register("http://champin.net", function(iri) { + var g = graph(); + g.addTriple(makeIri(iri), + makeIri("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + makeIri("http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource") + ); + return new BasicCore(iri, g); + }); + var me = iri("http://champin.net"); var ns = namespace("http://ex.co/vocab#"); var ressource = getCore(me); diff --git a/public/js/rdfrestbundle.js b/public/js/rdfrestbundle.js deleted file mode 100644 index 2f92905..0000000 --- a/public/js/rdfrestbundle.js +++ /dev/null @@ -1,18986 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { - ctx.push(tmp[i]); - } - } - - // remove array if only one context - var hasContext = (ctx.length > 0); - if(ctx.length === 1) { - ctx = ctx[0]; - } - - // add context and/or @graph - if(_isArray(compacted)) { - // use '@graph' keyword - var kwgraph = _compactIri(activeCtx, '@graph'); - var graph = compacted; - compacted = {}; - if(hasContext) { - compacted['@context'] = ctx; - } - compacted[kwgraph] = graph; - } else if(_isObject(compacted) && hasContext) { - // reorder keys so @context is first - var graph = compacted; - compacted = {'@context': ctx}; - for(var key in graph) { - compacted[key] = graph[key]; - } - } - - callback(null, compacted, activeCtx); - } -}; - -/** - * Performs JSON-LD expansion. - * - * @param input the JSON-LD input to expand. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [keepFreeFloatingNodes] true to keep free-floating nodes, - * false not to, defaults to false. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, expanded) called once the operation completes. - */ -jsonld.expand = function(input, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not expand, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - if(!('keepFreeFloatingNodes' in options)) { - options.keepFreeFloatingNodes = false; - } - - jsonld.nextTick(function() { - // if input is a string, attempt to dereference remote document - if(typeof input === 'string') { - var done = function(err, remoteDoc) { - if(err) { - return callback(err); - } - try { - if(!remoteDoc.document) { - throw new JsonLdError( - 'No remote document found at the given URL.', - 'jsonld.NullRemoteDocument'); - } - if(typeof remoteDoc.document === 'string') { - remoteDoc.document = JSON.parse(remoteDoc.document); - } - } catch(ex) { - return callback(new JsonLdError( - 'Could not retrieve a JSON-LD document from the URL. URL ' + - 'dereferencing not implemented.', 'jsonld.LoadDocumentError', { - code: 'loading document failed', - cause: ex, - remoteDoc: remoteDoc - })); - } - expand(remoteDoc); - }; - var promise = options.documentLoader(input, done); - if(promise && 'then' in promise) { - promise.then(done.bind(null, null), done); - } - return; - } - // nothing to load - expand({contextUrl: null, documentUrl: null, document: input}); - }); - - function expand(remoteDoc) { - // set default base - if(!('base' in options)) { - options.base = remoteDoc.documentUrl || ''; - } - // build meta-object and retrieve all @context URLs - var input = { - document: _clone(remoteDoc.document), - remoteContext: {'@context': remoteDoc.contextUrl} - }; - if('expandContext' in options) { - var expandContext = _clone(options.expandContext); - if(typeof expandContext === 'object' && '@context' in expandContext) { - input.expandContext = expandContext; - } else { - input.expandContext = {'@context': expandContext}; - } - } - _retrieveContextUrls(input, options, function(err, input) { - if(err) { - return callback(err); - } - - var expanded; - try { - var processor = new Processor(); - var activeCtx = _getInitialContext(options); - var document = input.document; - var remoteContext = input.remoteContext['@context']; - - // process optional expandContext - if(input.expandContext) { - activeCtx = processor.processContext( - activeCtx, input.expandContext['@context'], options); - } - - // process remote context from HTTP Link Header - if(remoteContext) { - activeCtx = processor.processContext( - activeCtx, remoteContext, options); - } - - // expand document - expanded = processor.expand( - activeCtx, null, document, options, false); - - // optimize away @graph with no other properties - if(_isObject(expanded) && ('@graph' in expanded) && - Object.keys(expanded).length === 1) { - expanded = expanded['@graph']; - } else if(expanded === null) { - expanded = []; - } - - // normalize to an array - if(!_isArray(expanded)) { - expanded = [expanded]; - } - } catch(ex) { - return callback(ex); - } - callback(null, expanded); - }); - } -}; - -/** - * Performs JSON-LD flattening. - * - * @param input the JSON-LD to flatten. - * @param ctx the context to use to compact the flattened output, or null. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, flattened) called once the operation completes. - */ -jsonld.flatten = function(input, ctx, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not flatten, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } else if(typeof ctx === 'function') { - callback = ctx; - ctx = null; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // expand input - jsonld.expand(input, options, function(err, _input) { - if(err) { - return callback(new JsonLdError( - 'Could not expand input before flattening.', - 'jsonld.FlattenError', {cause: err})); - } - - var flattened; - try { - // do flattening - flattened = new Processor().flatten(_input); - } catch(ex) { - return callback(ex); - } - - if(ctx === null) { - return callback(null, flattened); - } - - // compact result (force @graph option to true, skip expansion) - options.graph = true; - options.skipExpansion = true; - jsonld.compact(flattened, ctx, options, function(err, compacted) { - if(err) { - return callback(new JsonLdError( - 'Could not compact flattened output.', - 'jsonld.FlattenError', {cause: err})); - } - callback(null, compacted); - }); - }); -}; - -/** - * Performs JSON-LD framing. - * - * @param input the JSON-LD input to frame. - * @param frame the JSON-LD frame to use. - * @param [options] the framing options. - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [embed] default @embed flag: '@last', '@always', '@never', '@link' - * (default: '@last'). - * [explicit] default @explicit flag (default: false). - * [requireAll] default @requireAll flag (default: true). - * [omitDefault] default @omitDefault flag (default: false). - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, framed) called once the operation completes. - */ -jsonld.frame = function(input, frame, options, callback) { - if(arguments.length < 2) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not frame, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - if(!('embed' in options)) { - options.embed = '@last'; - } - options.explicit = options.explicit || false; - if(!('requireAll' in options)) { - options.requireAll = true; - } - options.omitDefault = options.omitDefault || false; - - jsonld.nextTick(function() { - // if frame is a string, attempt to dereference remote document - if(typeof frame === 'string') { - var done = function(err, remoteDoc) { - if(err) { - return callback(err); - } - try { - if(!remoteDoc.document) { - throw new JsonLdError( - 'No remote document found at the given URL.', - 'jsonld.NullRemoteDocument'); - } - if(typeof remoteDoc.document === 'string') { - remoteDoc.document = JSON.parse(remoteDoc.document); - } - } catch(ex) { - return callback(new JsonLdError( - 'Could not retrieve a JSON-LD document from the URL. URL ' + - 'dereferencing not implemented.', 'jsonld.LoadDocumentError', { - code: 'loading document failed', - cause: ex, - remoteDoc: remoteDoc - })); - } - doFrame(remoteDoc); - }; - var promise = options.documentLoader(frame, done); - if(promise && 'then' in promise) { - promise.then(done.bind(null, null), done); - } - return; - } - // nothing to load - doFrame({contextUrl: null, documentUrl: null, document: frame}); - }); - - function doFrame(remoteFrame) { - // preserve frame context and add any Link header context - var frame = remoteFrame.document; - var ctx; - if(frame) { - ctx = frame['@context']; - if(remoteFrame.contextUrl) { - if(!ctx) { - ctx = remoteFrame.contextUrl; - } else if(_isArray(ctx)) { - ctx.push(remoteFrame.contextUrl); - } else { - ctx = [ctx, remoteFrame.contextUrl]; - } - frame['@context'] = ctx; - } else { - ctx = ctx || {}; - } - } else { - ctx = {}; - } - - // expand input - jsonld.expand(input, options, function(err, expanded) { - if(err) { - return callback(new JsonLdError( - 'Could not expand input before framing.', - 'jsonld.FrameError', {cause: err})); - } - - // expand frame - var opts = _clone(options); - opts.isFrame = true; - opts.keepFreeFloatingNodes = true; - jsonld.expand(frame, opts, function(err, expandedFrame) { - if(err) { - return callback(new JsonLdError( - 'Could not expand frame before framing.', - 'jsonld.FrameError', {cause: err})); - } - - var framed; - try { - // do framing - framed = new Processor().frame(expanded, expandedFrame, opts); - } catch(ex) { - return callback(ex); - } - - // compact result (force @graph option to true, skip expansion, - // check for linked embeds) - opts.graph = true; - opts.skipExpansion = true; - opts.link = {}; - jsonld.compact(framed, ctx, opts, function(err, compacted, ctx) { - if(err) { - return callback(new JsonLdError( - 'Could not compact framed output.', - 'jsonld.FrameError', {cause: err})); - } - // get graph alias - var graph = _compactIri(ctx, '@graph'); - // remove @preserve from results - opts.link = {}; - compacted[graph] = _removePreserve(ctx, compacted[graph], opts); - callback(null, compacted); - }); - }); - }); - } -}; - -/** - * **Experimental** - * - * Links a JSON-LD document's nodes in memory. - * - * @param input the JSON-LD document to link. - * @param ctx the JSON-LD context to apply. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, linked) called once the operation completes. - */ -jsonld.link = function(input, ctx, options, callback) { - // API matches running frame with a wildcard frame and embed: '@link' - // get arguments - var frame = {}; - if(ctx) { - frame['@context'] = ctx; - } - frame['@embed'] = '@link'; - jsonld.frame(input, frame, options, callback); -}; - -/** - * **Deprecated** - * - * Performs JSON-LD objectification. - * - * @param input the JSON-LD document to objectify. - * @param ctx the JSON-LD context to apply. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, linked) called once the operation completes. - */ -jsonld.objectify = function(input, ctx, options, callback) { - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // expand input - jsonld.expand(input, options, function(err, _input) { - if(err) { - return callback(new JsonLdError( - 'Could not expand input before linking.', - 'jsonld.LinkError', {cause: err})); - } - - var flattened; - try { - // flatten the graph - flattened = new Processor().flatten(_input); - } catch(ex) { - return callback(ex); - } - - // compact result (force @graph option to true, skip expansion) - options.graph = true; - options.skipExpansion = true; - jsonld.compact(flattened, ctx, options, function(err, compacted, ctx) { - if(err) { - return callback(new JsonLdError( - 'Could not compact flattened output before linking.', - 'jsonld.LinkError', {cause: err})); - } - // get graph alias - var graph = _compactIri(ctx, '@graph'); - var top = compacted[graph][0]; - - var recurse = function(subject) { - // can't replace just a string - if(!_isObject(subject) && !_isArray(subject)) { - return; - } - - // bottom out recursion on re-visit - if(_isObject(subject)) { - if(recurse.visited[subject['@id']]) { - return; - } - recurse.visited[subject['@id']] = true; - } - - // each array element *or* object key - for(var k in subject) { - var obj = subject[k]; - var isid = (jsonld.getContextValue(ctx, k, '@type') === '@id'); - - // can't replace a non-object or non-array unless it's an @id - if(!_isArray(obj) && !_isObject(obj) && !isid) { - continue; - } - - if(_isString(obj) && isid) { - subject[k] = obj = top[obj]; - recurse(obj); - } else if(_isArray(obj)) { - for(var i = 0; i < obj.length; ++i) { - if(_isString(obj[i]) && isid) { - obj[i] = top[obj[i]]; - } else if(_isObject(obj[i]) && '@id' in obj[i]) { - obj[i] = top[obj[i]['@id']]; - } - recurse(obj[i]); - } - } else if(_isObject(obj)) { - var sid = obj['@id']; - subject[k] = obj = top[sid]; - recurse(obj); - } - } - }; - recurse.visited = {}; - recurse(top); - - compacted.of_type = {}; - for(var s in top) { - if(!('@type' in top[s])) { - continue; - } - var types = top[s]['@type']; - if(!_isArray(types)) { - types = [types]; - } - for(var t in types) { - if(!(types[t] in compacted.of_type)) { - compacted.of_type[types[t]] = []; - } - compacted.of_type[types[t]].push(top[s]); - } - } - callback(null, compacted); - }); - }); -}; - -/** - * Performs RDF dataset normalization on the given JSON-LD input. The output - * is an RDF dataset unless the 'format' option is used. - * - * @param input the JSON-LD input to normalize. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [format] the format if output is a string: - * 'application/nquads' for N-Quads. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, normalized) called once the operation completes. - */ -jsonld.normalize = function(input, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not normalize, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // convert to RDF dataset then do normalization - var opts = _clone(options); - delete opts.format; - opts.produceGeneralizedRdf = false; - jsonld.toRDF(input, opts, function(err, dataset) { - if(err) { - return callback(new JsonLdError( - 'Could not convert input to RDF dataset before normalization.', - 'jsonld.NormalizeError', {cause: err})); - } - - // do normalization - new Processor().normalize(dataset, options, callback); - }); -}; - -/** - * Converts an RDF dataset to JSON-LD. - * - * @param dataset a serialized string of RDF in a format specified by the - * format option or an RDF dataset to convert. - * @param [options] the options to use: - * [format] the format if dataset param must first be parsed: - * 'application/nquads' for N-Quads (default). - * [rdfParser] a custom RDF-parser to use to parse the dataset. - * [useRdfType] true to use rdf:type, false to use @type - * (default: false). - * [useNativeTypes] true to convert XSD types into native types - * (boolean, integer, double), false not to (default: false). - * @param callback(err, output) called once the operation completes. - */ -jsonld.fromRDF = function(dataset, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not convert from RDF, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('useRdfType' in options)) { - options.useRdfType = false; - } - if(!('useNativeTypes' in options)) { - options.useNativeTypes = false; - } - - if(!('format' in options) && _isString(dataset)) { - // set default format to nquads - if(!('format' in options)) { - options.format = 'application/nquads'; - } - } - - jsonld.nextTick(function() { - // handle special format - var rdfParser; - if(options.format) { - // check supported formats - rdfParser = options.rdfParser || _rdfParsers[options.format]; - if(!rdfParser) { - return callback(new JsonLdError( - 'Unknown input format.', - 'jsonld.UnknownFormat', {format: options.format})); - } - } else { - // no-op parser, assume dataset already parsed - rdfParser = function() { - return dataset; - }; - } - - // rdf parser may be async or sync, always pass callback - dataset = rdfParser(dataset, function(err, dataset) { - if(err) { - return callback(err); - } - fromRDF(dataset, options, callback); - }); - // handle synchronous or promise-based parser - if(dataset) { - // if dataset is actually a promise - if('then' in dataset) { - return dataset.then(function(dataset) { - fromRDF(dataset, options, callback); - }, callback); - } - // parser is synchronous - fromRDF(dataset, options, callback); - } - - function fromRDF(dataset, options, callback) { - // convert from RDF - new Processor().fromRDF(dataset, options, callback); - } - }); -}; - -/** - * Outputs the RDF dataset found in the given JSON-LD object. - * - * @param input the JSON-LD input. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [format] the format to use to output a string: - * 'application/nquads' for N-Quads. - * [produceGeneralizedRdf] true to output generalized RDF, false - * to produce only standard RDF (default: false). - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, dataset) called once the operation completes. - */ -jsonld.toRDF = function(input, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not convert to RDF, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // expand input - jsonld.expand(input, options, function(err, expanded) { - if(err) { - return callback(new JsonLdError( - 'Could not expand input before serialization to RDF.', - 'jsonld.RdfError', {cause: err})); - } - - var dataset; - try { - // output RDF dataset - dataset = Processor.prototype.toRDF(expanded, options); - if(options.format) { - if(options.format === 'application/nquads') { - return callback(null, _toNQuads(dataset)); - } - throw new JsonLdError( - 'Unknown output format.', - 'jsonld.UnknownFormat', {format: options.format}); - } - } catch(ex) { - return callback(ex); - } - callback(null, dataset); - }); -}; - -/** - * **Experimental** - * - * Recursively flattens the nodes in the given JSON-LD input into a map of - * node ID => node. - * - * @param input the JSON-LD input. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [namer] a jsonld.UniqueNamer to use to label blank nodes. - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, nodeMap) called once the operation completes. - */ -jsonld.createNodeMap = function(input, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not create node map, too few arguments.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // set default options - if(!('base' in options)) { - options.base = (typeof input === 'string') ? input : ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // expand input - jsonld.expand(input, options, function(err, _input) { - if(err) { - return callback(new JsonLdError( - 'Could not expand input before creating node map.', - 'jsonld.CreateNodeMapError', {cause: err})); - } - - var nodeMap; - try { - nodeMap = new Processor().createNodeMap(_input, options); - } catch(ex) { - return callback(ex); - } - - callback(null, nodeMap); - }); -}; - -/** - * **Experimental** - * - * Merges two or more JSON-LD documents into a single flattened document. - * - * @param docs the JSON-LD documents to merge together. - * @param ctx the context to use to compact the merged result, or null. - * @param [options] the options to use: - * [base] the base IRI to use. - * [expandContext] a context to expand with. - * [namer] a jsonld.UniqueNamer to use to label blank nodes. - * [mergeNodes] true to merge properties for nodes with the same ID, - * false to ignore new properties for nodes with the same ID once - * the ID has been defined; note that this may not prevent merging - * new properties where a node is in the `object` position - * (default: true). - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, merged) called once the operation completes. - */ -jsonld.merge = function(docs, ctx, options, callback) { - if(arguments.length < 1) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not merge, too few arguments.')); - }); - } - if(!_isArray(docs)) { - return jsonld.nextTick(function() { - callback(new TypeError('Could not merge, "docs" must be an array.')); - }); - } - - // get arguments - if(typeof options === 'function') { - callback = options; - options = {}; - } else if(typeof ctx === 'function') { - callback = ctx; - ctx = null; - options = {}; - } - options = options || {}; - - // expand all documents - var expanded = []; - var error = null; - var count = docs.length; - for(var i = 0; i < docs.length; ++i) { - var opts = {}; - for(var key in options) { - opts[key] = options[key]; - } - jsonld.expand(docs[i], opts, expandComplete); - } - - function expandComplete(err, _input) { - if(error) { - return; - } - if(err) { - error = err; - return callback(new JsonLdError( - 'Could not expand input before flattening.', - 'jsonld.FlattenError', {cause: err})); - } - expanded.push(_input); - if(--count === 0) { - merge(expanded); - } - } - - function merge(expanded) { - var mergeNodes = true; - if('mergeNodes' in options) { - mergeNodes = options.mergeNodes; - } - - var namer = options.namer || new UniqueNamer('_:b'); - var graphs = {'@default': {}}; - - var defaultGraph; - try { - for(var i = 0; i < expanded.length; ++i) { - // uniquely relabel blank nodes - var doc = expanded[i]; - doc = jsonld.relabelBlankNodes(doc, { - namer: new UniqueNamer('_:b' + i + '-') - }); - - // add nodes to the shared node map graphs if merging nodes, to a - // separate graph set if not - var _graphs = (mergeNodes || i === 0) ? graphs : {'@default': {}}; - _createNodeMap(doc, _graphs, '@default', namer); - - if(_graphs !== graphs) { - // merge document graphs but don't merge existing nodes - for(var graphName in _graphs) { - var _nodeMap = _graphs[graphName]; - if(!(graphName in graphs)) { - graphs[graphName] = _nodeMap; - continue; - } - var nodeMap = graphs[graphName]; - for(var key in _nodeMap) { - if(!(key in nodeMap)) { - nodeMap[key] = _nodeMap[key]; - } - } - } - } - } - - // add all non-default graphs to default graph - defaultGraph = _mergeNodeMaps(graphs); - } catch(ex) { - return callback(ex); - } - - // produce flattened output - var flattened = []; - var keys = Object.keys(defaultGraph).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var node = defaultGraph[keys[ki]]; - // only add full subjects to top-level - if(!_isSubjectReference(node)) { - flattened.push(node); - } - } - - if(ctx === null) { - return callback(null, flattened); - } - - // compact result (force @graph option to true, skip expansion) - options.graph = true; - options.skipExpansion = true; - jsonld.compact(flattened, ctx, options, function(err, compacted) { - if(err) { - return callback(new JsonLdError( - 'Could not compact merged output.', - 'jsonld.MergeError', {cause: err})); - } - callback(null, compacted); - }); - } -}; - -/** - * Relabels all blank nodes in the given JSON-LD input. - * - * @param input the JSON-LD input. - * @param [options] the options to use: - * [namer] a jsonld.UniqueNamer to use. - */ -jsonld.relabelBlankNodes = function(input, options) { - options = options || {}; - var namer = options.namer || new UniqueNamer('_:b'); - return _labelBlankNodes(namer, input); -}; - -/** - * The default document loader for external documents. If the environment - * is node.js, a callback-continuation-style document loader is used; otherwise, - * a promises-style document loader is used. - * - * @param url the URL to load. - * @param callback(err, remoteDoc) called once the operation completes, - * if using a non-promises API. - * - * @return a promise, if using a promises API. - */ -jsonld.documentLoader = function(url, callback) { - var err = new JsonLdError( - 'Could not retrieve a JSON-LD document from the URL. URL ' + - 'dereferencing not implemented.', 'jsonld.LoadDocumentError', - {code: 'loading document failed'}); - if(_nodejs) { - return callback(err, {contextUrl: null, documentUrl: url, document: null}); - } - return jsonld.promisify(function(callback) { - callback(err); - }); -}; - -/** - * Deprecated default document loader. Use or override jsonld.documentLoader - * instead. - */ -jsonld.loadDocument = function(url, callback) { - var promise = jsonld.documentLoader(url, callback); - if(promise && 'then' in promise) { - promise.then(callback.bind(null, null), callback); - } -}; - -/* Promises API */ - -/** - * Creates a new promises API object. - * - * @param [options] the options to use: - * [api] an object to attach the API to. - * [version] 'json-ld-1.0' to output a standard JSON-LD 1.0 promises - * API, 'jsonld.js' to output the same with augmented proprietary - * methods (default: 'jsonld.js') - * - * @return the promises API object. - */ -jsonld.promises = function(options) { - options = options || {}; - var slice = Array.prototype.slice; - var promisify = jsonld.promisify; - - // handle 'api' option as version, set defaults - var api = options.api || {}; - var version = options.version || 'jsonld.js'; - if(typeof options.api === 'string') { - if(!options.version) { - version = options.api; - } - api = {}; - } - - api.expand = function(input) { - if(arguments.length < 1) { - throw new TypeError('Could not expand, too few arguments.'); - } - return promisify.apply(null, [jsonld.expand].concat(slice.call(arguments))); - }; - api.compact = function(input, ctx) { - if(arguments.length < 2) { - throw new TypeError('Could not compact, too few arguments.'); - } - var compact = function(input, ctx, options, callback) { - // ensure only one value is returned in callback - jsonld.compact(input, ctx, options, function(err, compacted) { - callback(err, compacted); - }); - }; - return promisify.apply(null, [compact].concat(slice.call(arguments))); - }; - api.flatten = function(input) { - if(arguments.length < 1) { - throw new TypeError('Could not flatten, too few arguments.'); - } - return promisify.apply( - null, [jsonld.flatten].concat(slice.call(arguments))); - }; - api.frame = function(input, frame) { - if(arguments.length < 2) { - throw new TypeError('Could not frame, too few arguments.'); - } - return promisify.apply(null, [jsonld.frame].concat(slice.call(arguments))); - }; - api.fromRDF = function(dataset) { - if(arguments.length < 1) { - throw new TypeError('Could not convert from RDF, too few arguments.'); - } - return promisify.apply( - null, [jsonld.fromRDF].concat(slice.call(arguments))); - }; - api.toRDF = function(input) { - if(arguments.length < 1) { - throw new TypeError('Could not convert to RDF, too few arguments.'); - } - return promisify.apply(null, [jsonld.toRDF].concat(slice.call(arguments))); - }; - api.normalize = function(input) { - if(arguments.length < 1) { - throw new TypeError('Could not normalize, too few arguments.'); - } - return promisify.apply( - null, [jsonld.normalize].concat(slice.call(arguments))); - }; - - if(version === 'jsonld.js') { - api.link = function(input, ctx) { - if(arguments.length < 2) { - throw new TypeError('Could not link, too few arguments.'); - } - return promisify.apply( - null, [jsonld.link].concat(slice.call(arguments))); - }; - api.objectify = function(input) { - return promisify.apply( - null, [jsonld.objectify].concat(slice.call(arguments))); - }; - api.createNodeMap = function(input) { - return promisify.apply( - null, [jsonld.createNodeMap].concat(slice.call(arguments))); - }; - api.merge = function(input) { - return promisify.apply( - null, [jsonld.merge].concat(slice.call(arguments))); - }; - } - - try { - jsonld.Promise = global.Promise || require('es6-promise').Promise; - } catch(e) { - var f = function() { - throw new Error('Unable to find a Promise implementation.'); - }; - for(var method in api) { - api[method] = f; - } - } - - return api; -}; - -/** - * Converts a node.js async op into a promise w/boxed resolved value(s). - * - * @param op the operation to convert. - * - * @return the promise. - */ -jsonld.promisify = function(op) { - if(!jsonld.Promise) { - try { - jsonld.Promise = global.Promise || require('es6-promise').Promise; - } catch(e) { - throw new Error('Unable to find a Promise implementation.'); - } - } - var args = Array.prototype.slice.call(arguments, 1); - return new jsonld.Promise(function(resolve, reject) { - op.apply(null, args.concat(function(err, value) { - if(!err) { - resolve(value); - } else { - reject(err); - } - })); - }); -}; - -// extend jsonld.promises w/jsonld.js methods -jsonld.promises({api: jsonld.promises}); - -/* WebIDL API */ - -function JsonLdProcessor() {} -JsonLdProcessor.prototype = jsonld.promises({version: 'json-ld-1.0'}); -JsonLdProcessor.prototype.toString = function() { - if(this instanceof JsonLdProcessor) { - return '[object JsonLdProcessor]'; - } - return '[object JsonLdProcessorPrototype]'; -}; -jsonld.JsonLdProcessor = JsonLdProcessor; - -// IE8 has Object.defineProperty but it only -// works on DOM nodes -- so feature detection -// requires try/catch :-( -var canDefineProperty = !!Object.defineProperty; -if(canDefineProperty) { - try { - Object.defineProperty({}, 'x', {}); - } catch(e) { - canDefineProperty = false; - } -} - -if(canDefineProperty) { - Object.defineProperty(JsonLdProcessor, 'prototype', { - writable: false, - enumerable: false - }); - Object.defineProperty(JsonLdProcessor.prototype, 'constructor', { - writable: true, - enumerable: false, - configurable: true, - value: JsonLdProcessor - }); -} - -// setup browser global JsonLdProcessor -if(_browser && typeof global.JsonLdProcessor === 'undefined') { - if(canDefineProperty) { - Object.defineProperty(global, 'JsonLdProcessor', { - writable: true, - enumerable: false, - configurable: true, - value: JsonLdProcessor - }); - } else { - global.JsonLdProcessor = JsonLdProcessor; - } -} - -/* Utility API */ - -// define setImmediate and nextTick -if(typeof process === 'undefined' || !process.nextTick) { - if(typeof setImmediate === 'function') { - jsonld.setImmediate = jsonld.nextTick = function(callback) { - return setImmediate(callback); - }; - } else { - jsonld.setImmediate = function(callback) { - setTimeout(callback, 0); - }; - jsonld.nextTick = jsonld.setImmediate; - } -} else { - jsonld.nextTick = process.nextTick; - if(typeof setImmediate === 'function') { - jsonld.setImmediate = setImmediate; - } else { - jsonld.setImmediate = jsonld.nextTick; - } -} - -/** - * Parses a link header. The results will be key'd by the value of "rel". - * - * Link: ; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json" - * - * Parses as: { - * 'http://www.w3.org/ns/json-ld#context': { - * target: http://json-ld.org/contexts/person.jsonld, - * type: 'application/ld+json' - * } - * } - * - * If there is more than one "rel" with the same IRI, then entries in the - * resulting map for that "rel" will be arrays. - * - * @param header the link header to parse. - */ -jsonld.parseLinkHeader = function(header) { - var rval = {}; - // split on unbracketed/unquoted commas - var entries = header.match(/(?:<[^>]*?>|"[^"]*?"|[^,])+/g); - var rLinkHeader = /\s*<([^>]*?)>\s*(?:;\s*(.*))?/; - for(var i = 0; i < entries.length; ++i) { - var match = entries[i].match(rLinkHeader); - if(!match) { - continue; - } - var result = {target: match[1]}; - var params = match[2]; - var rParams = /(.*?)=(?:(?:"([^"]*?)")|([^"]*?))\s*(?:(?:;\s*)|$)/g; - while(match = rParams.exec(params)) { - result[match[1]] = (match[2] === undefined) ? match[3] : match[2]; - } - var rel = result['rel'] || ''; - if(_isArray(rval[rel])) { - rval[rel].push(result); - } else if(rel in rval) { - rval[rel] = [rval[rel], result]; - } else { - rval[rel] = result; - } - } - return rval; -}; - -/** - * Creates a simple document cache that retains documents for a short - * period of time. - * - * FIXME: Implement simple HTTP caching instead. - * - * @param size the maximum size of the cache. - */ -jsonld.DocumentCache = function(size) { - this.order = []; - this.cache = {}; - this.size = size || 50; - this.expires = 30 * 1000; -}; -jsonld.DocumentCache.prototype.get = function(url) { - if(url in this.cache) { - var entry = this.cache[url]; - if(entry.expires >= +new Date()) { - return entry.ctx; - } - delete this.cache[url]; - this.order.splice(this.order.indexOf(url), 1); - } - return null; -}; -jsonld.DocumentCache.prototype.set = function(url, ctx) { - if(this.order.length === this.size) { - delete this.cache[this.order.shift()]; - } - this.order.push(url); - this.cache[url] = {ctx: ctx, expires: (+new Date() + this.expires)}; -}; - -/** - * Creates an active context cache. - * - * @param size the maximum size of the cache. - */ -jsonld.ActiveContextCache = function(size) { - this.order = []; - this.cache = {}; - this.size = size || 100; -}; -jsonld.ActiveContextCache.prototype.get = function(activeCtx, localCtx) { - var key1 = JSON.stringify(activeCtx); - var key2 = JSON.stringify(localCtx); - var level1 = this.cache[key1]; - if(level1 && key2 in level1) { - return level1[key2]; - } - return null; -}; -jsonld.ActiveContextCache.prototype.set = function( - activeCtx, localCtx, result) { - if(this.order.length === this.size) { - var entry = this.order.shift(); - delete this.cache[entry.activeCtx][entry.localCtx]; - } - var key1 = JSON.stringify(activeCtx); - var key2 = JSON.stringify(localCtx); - this.order.push({activeCtx: key1, localCtx: key2}); - if(!(key1 in this.cache)) { - this.cache[key1] = {}; - } - this.cache[key1][key2] = _clone(result); -}; - -/** - * Default JSON-LD cache. - */ -jsonld.cache = { - activeCtx: new jsonld.ActiveContextCache() -}; - -/** - * Document loaders. - */ -jsonld.documentLoaders = {}; - -/** - * Creates a built-in jquery document loader. - * - * @param $ the jquery instance to use. - * @param options the options to use: - * secure: require all URLs to use HTTPS. - * usePromise: true to use a promises API, false for a - * callback-continuation-style API; defaults to true if Promise - * is globally defined, false if not. - * - * @return the jquery document loader. - */ -jsonld.documentLoaders.jquery = function($, options) { - options = options || {}; - var loader = function(url, callback) { - if(url.indexOf('http:') !== 0 && url.indexOf('https:') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; only "http" and "https" URLs are ' + - 'supported.', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - if(options.secure && url.indexOf('https') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; secure mode is enabled and ' + - 'the URL\'s scheme is not "https".', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - $.ajax({ - url: url, - accepts: { - json: 'application/ld+json, application/json' - }, - // ensure Accept header is very specific for JSON-LD/JSON - headers: { - 'Accept': 'application/ld+json, application/json' - }, - dataType: 'json', - crossDomain: true, - success: function(data, textStatus, jqXHR) { - var doc = {contextUrl: null, documentUrl: url, document: data}; - - // handle Link Header - var contentType = jqXHR.getResponseHeader('Content-Type'); - var linkHeader = jqXHR.getResponseHeader('Link'); - if(linkHeader && contentType !== 'application/ld+json') { - // only 1 related link header permitted - linkHeader = jsonld.parseLinkHeader(linkHeader)[LINK_HEADER_REL]; - if(_isArray(linkHeader)) { - return callback(new JsonLdError( - 'URL could not be dereferenced, it has more than one ' + - 'associated HTTP Link Header.', - 'jsonld.InvalidUrl', - {code: 'multiple context link headers', url: url}), doc); - } - if(linkHeader) { - doc.contextUrl = linkHeader.target; - } - } - - callback(null, doc); - }, - error: function(jqXHR, textStatus, err) { - callback(new JsonLdError( - 'URL could not be dereferenced, an error occurred.', - 'jsonld.LoadDocumentError', - {code: 'loading document failed', url: url, cause: err}), - {contextUrl: null, documentUrl: url, document: null}); - } - }); - }; - - var usePromise = (typeof Promise !== 'undefined'); - if('usePromise' in options) { - usePromise = options.usePromise; - } - if(usePromise) { - return function(url) { - return jsonld.promisify(loader, url); - }; - } - return loader; -}; - -/** - * Creates a built-in node document loader. - * - * @param options the options to use: - * secure: require all URLs to use HTTPS. - * strictSSL: true to require SSL certificates to be valid, - * false not to (default: true). - * maxRedirects: the maximum number of redirects to permit, none by - * default. - * usePromise: true to use a promises API, false for a - * callback-continuation-style API; false by default. - * - * @return the node document loader. - */ -jsonld.documentLoaders.node = function(options) { - options = options || {}; - var strictSSL = ('strictSSL' in options) ? options.strictSSL : true; - var maxRedirects = ('maxRedirects' in options) ? options.maxRedirects : -1; - var request = require('request'); - var http = require('http'); - var cache = new jsonld.DocumentCache(); - function loadDocument(url, redirects, callback) { - if(url.indexOf('http:') !== 0 && url.indexOf('https:') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; only "http" and "https" URLs are ' + - 'supported.', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - if(options.secure && url.indexOf('https') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; secure mode is enabled and ' + - 'the URL\'s scheme is not "https".', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - var doc = cache.get(url); - if(doc !== null) { - return callback(null, doc); - } - request({ - url: url, - headers: { - 'Accept': 'application/ld+json, application/json' - }, - strictSSL: strictSSL, - followRedirect: false - }, handleResponse); - - function handleResponse(err, res, body) { - doc = {contextUrl: null, documentUrl: url, document: body || null}; - - // handle error - if(err) { - return callback(new JsonLdError( - 'URL could not be dereferenced, an error occurred.', - 'jsonld.LoadDocumentError', - {code: 'loading document failed', url: url, cause: err}), doc); - } - var statusText = http.STATUS_CODES[res.statusCode]; - if(res.statusCode >= 400) { - return callback(new JsonLdError( - 'URL could not be dereferenced: ' + statusText, - 'jsonld.InvalidUrl', { - code: 'loading document failed', - url: url, - httpStatusCode: res.statusCode - }), doc); - } - - // handle Link Header - if(res.headers.link && - res.headers['content-type'] !== 'application/ld+json') { - // only 1 related link header permitted - var linkHeader = jsonld.parseLinkHeader( - res.headers.link)[LINK_HEADER_REL]; - if(_isArray(linkHeader)) { - return callback(new JsonLdError( - 'URL could not be dereferenced, it has more than one associated ' + - 'HTTP Link Header.', - 'jsonld.InvalidUrl', - {code: 'multiple context link headers', url: url}), doc); - } - if(linkHeader) { - doc.contextUrl = linkHeader.target; - } - } - - // handle redirect - if(res.statusCode >= 300 && res.statusCode < 400 && - res.headers.location) { - if(redirects.length === maxRedirects) { - return callback(new JsonLdError( - 'URL could not be dereferenced; there were too many redirects.', - 'jsonld.TooManyRedirects', { - code: 'loading document failed', - url: url, - httpStatusCode: res.statusCode, - redirects: redirects - }), doc); - } - if(redirects.indexOf(url) !== -1) { - return callback(new JsonLdError( - 'URL could not be dereferenced; infinite redirection was detected.', - 'jsonld.InfiniteRedirectDetected', { - code: 'recursive context inclusion', - url: url, - httpStatusCode: res.statusCode, - redirects: redirects - }), doc); - } - redirects.push(url); - return loadDocument(res.headers.location, redirects, callback); - } - // cache for each redirected URL - redirects.push(url); - for(var i = 0; i < redirects.length; ++i) { - cache.set( - redirects[i], - {contextUrl: null, documentUrl: redirects[i], document: body}); - } - callback(err, doc); - } - } - - var loader = function(url, callback) { - loadDocument(url, [], callback); - }; - if(options.usePromise) { - return function(url) { - return jsonld.promisify(loader, url); - }; - } - return loader; -}; - -/** - * Creates a built-in XMLHttpRequest document loader. - * - * @param options the options to use: - * secure: require all URLs to use HTTPS. - * usePromise: true to use a promises API, false for a - * callback-continuation-style API; defaults to true if Promise - * is globally defined, false if not. - * [xhr]: the XMLHttpRequest API to use. - * - * @return the XMLHttpRequest document loader. - */ -jsonld.documentLoaders.xhr = function(options) { - var rlink = /(^|(\r\n))link:/i; - options = options || {}; - var loader = function(url, callback) { - if(url.indexOf('http:') !== 0 && url.indexOf('https:') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; only "http" and "https" URLs are ' + - 'supported.', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - if(options.secure && url.indexOf('https') !== 0) { - return callback(new JsonLdError( - 'URL could not be dereferenced; secure mode is enabled and ' + - 'the URL\'s scheme is not "https".', - 'jsonld.InvalidUrl', {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - } - var xhr = options.xhr || XMLHttpRequest; - var req = new xhr(); - req.onload = function(e) { - if(req.status >= 400) { - return callback(new JsonLdError( - 'URL could not be dereferenced: ' + req.statusText, - 'jsonld.LoadDocumentError', { - code: 'loading document failed', - url: url, - httpStatusCode: req.status - }), {contextUrl: null, documentUrl: url, document: null}); - } - - var doc = {contextUrl: null, documentUrl: url, document: req.response}; - - // handle Link Header (avoid unsafe header warning by existence testing) - var contentType = req.getResponseHeader('Content-Type'); - var linkHeader; - if(rlink.test(req.getAllResponseHeaders())) { - linkHeader = req.getResponseHeader('Link'); - } - if(linkHeader && contentType !== 'application/ld+json') { - // only 1 related link header permitted - linkHeader = jsonld.parseLinkHeader(linkHeader)[LINK_HEADER_REL]; - if(_isArray(linkHeader)) { - return callback(new JsonLdError( - 'URL could not be dereferenced, it has more than one ' + - 'associated HTTP Link Header.', - 'jsonld.InvalidUrl', - {code: 'multiple context link headers', url: url}), doc); - } - if(linkHeader) { - doc.contextUrl = linkHeader.target; - } - } - - callback(null, doc); - }; - req.onerror = function() { - callback(new JsonLdError( - 'URL could not be dereferenced, an error occurred.', - 'jsonld.LoadDocumentError', - {code: 'loading document failed', url: url}), - {contextUrl: null, documentUrl: url, document: null}); - }; - req.open('GET', url, true); - req.setRequestHeader('Accept', 'application/ld+json, application/json'); - req.send(); - }; - - var usePromise = (typeof Promise !== 'undefined'); - if('usePromise' in options) { - usePromise = options.usePromise; - } - if(usePromise) { - return function(url) { - return jsonld.promisify(loader, url); - }; - } - return loader; -}; - -/** - * Assigns the default document loader for external document URLs to a built-in - * default. Supported types currently include: 'jquery' and 'node'. - * - * To use the jquery document loader, the first parameter must be a reference - * to the main jquery object. - * - * @param type the type to set. - * @param [params] the parameters required to use the document loader. - */ -jsonld.useDocumentLoader = function(type) { - if(!(type in jsonld.documentLoaders)) { - throw new JsonLdError( - 'Unknown document loader type: "' + type + '"', - 'jsonld.UnknownDocumentLoader', - {type: type}); - } - - // set document loader - jsonld.documentLoader = jsonld.documentLoaders[type].apply( - jsonld, Array.prototype.slice.call(arguments, 1)); -}; - -/** - * Processes a local context, resolving any URLs as necessary, and returns a - * new active context in its callback. - * - * @param activeCtx the current active context. - * @param localCtx the local context to process. - * @param [options] the options to use: - * [documentLoader(url, callback(err, remoteDoc))] the document loader. - * @param callback(err, ctx) called once the operation completes. - */ -jsonld.processContext = function(activeCtx, localCtx) { - // get arguments - var options = {}; - var callbackArg = 2; - if(arguments.length > 3) { - options = arguments[2] || {}; - callbackArg += 1; - } - var callback = arguments[callbackArg]; - - // set default options - if(!('base' in options)) { - options.base = ''; - } - if(!('documentLoader' in options)) { - options.documentLoader = jsonld.loadDocument; - } - - // return initial context early for null context - if(localCtx === null) { - return callback(null, _getInitialContext(options)); - } - - // retrieve URLs in localCtx - localCtx = _clone(localCtx); - if(!(_isObject(localCtx) && '@context' in localCtx)) { - localCtx = {'@context': localCtx}; - } - _retrieveContextUrls(localCtx, options, function(err, ctx) { - if(err) { - return callback(err); - } - try { - // process context - ctx = new Processor().processContext(activeCtx, ctx, options); - } catch(ex) { - return callback(ex); - } - callback(null, ctx); - }); -}; - -/** - * Returns true if the given subject has the given property. - * - * @param subject the subject to check. - * @param property the property to look for. - * - * @return true if the subject has the given property, false if not. - */ -jsonld.hasProperty = function(subject, property) { - var rval = false; - if(property in subject) { - var value = subject[property]; - rval = (!_isArray(value) || value.length > 0); - } - return rval; -}; - -/** - * Determines if the given value is a property of the given subject. - * - * @param subject the subject to check. - * @param property the property to check. - * @param value the value to check. - * - * @return true if the value exists, false if not. - */ -jsonld.hasValue = function(subject, property, value) { - var rval = false; - if(jsonld.hasProperty(subject, property)) { - var val = subject[property]; - var isList = _isList(val); - if(_isArray(val) || isList) { - if(isList) { - val = val['@list']; - } - for(var i = 0; i < val.length; ++i) { - if(jsonld.compareValues(value, val[i])) { - rval = true; - break; - } - } - } else if(!_isArray(value)) { - // avoid matching the set of values with an array value parameter - rval = jsonld.compareValues(value, val); - } - } - return rval; -}; - -/** - * Adds a value to a subject. If the value is an array, all values in the - * array will be added. - * - * @param subject the subject to add the value to. - * @param property the property that relates the value to the subject. - * @param value the value to add. - * @param [options] the options to use: - * [propertyIsArray] true if the property is always an array, false - * if not (default: false). - * [allowDuplicate] true to allow duplicates, false not to (uses a - * simple shallow comparison of subject ID or value) (default: true). - */ -jsonld.addValue = function(subject, property, value, options) { - options = options || {}; - if(!('propertyIsArray' in options)) { - options.propertyIsArray = false; - } - if(!('allowDuplicate' in options)) { - options.allowDuplicate = true; - } - - if(_isArray(value)) { - if(value.length === 0 && options.propertyIsArray && - !(property in subject)) { - subject[property] = []; - } - for(var i = 0; i < value.length; ++i) { - jsonld.addValue(subject, property, value[i], options); - } - } else if(property in subject) { - // check if subject already has value if duplicates not allowed - var hasValue = (!options.allowDuplicate && - jsonld.hasValue(subject, property, value)); - - // make property an array if value not present or always an array - if(!_isArray(subject[property]) && - (!hasValue || options.propertyIsArray)) { - subject[property] = [subject[property]]; - } - - // add new value - if(!hasValue) { - subject[property].push(value); - } - } else { - // add new value as set or single value - subject[property] = options.propertyIsArray ? [value] : value; - } -}; - -/** - * Gets all of the values for a subject's property as an array. - * - * @param subject the subject. - * @param property the property. - * - * @return all of the values for a subject's property as an array. - */ -jsonld.getValues = function(subject, property) { - var rval = subject[property] || []; - if(!_isArray(rval)) { - rval = [rval]; - } - return rval; -}; - -/** - * Removes a property from a subject. - * - * @param subject the subject. - * @param property the property. - */ -jsonld.removeProperty = function(subject, property) { - delete subject[property]; -}; - -/** - * Removes a value from a subject. - * - * @param subject the subject. - * @param property the property that relates the value to the subject. - * @param value the value to remove. - * @param [options] the options to use: - * [propertyIsArray] true if the property is always an array, false - * if not (default: false). - */ -jsonld.removeValue = function(subject, property, value, options) { - options = options || {}; - if(!('propertyIsArray' in options)) { - options.propertyIsArray = false; - } - - // filter out value - var values = jsonld.getValues(subject, property).filter(function(e) { - return !jsonld.compareValues(e, value); - }); - - if(values.length === 0) { - jsonld.removeProperty(subject, property); - } else if(values.length === 1 && !options.propertyIsArray) { - subject[property] = values[0]; - } else { - subject[property] = values; - } -}; - -/** - * Compares two JSON-LD values for equality. Two JSON-LD values will be - * considered equal if: - * - * 1. They are both primitives of the same type and value. - * 2. They are both @values with the same @value, @type, @language, - * and @index, OR - * 3. They both have @ids they are the same. - * - * @param v1 the first value. - * @param v2 the second value. - * - * @return true if v1 and v2 are considered equal, false if not. - */ -jsonld.compareValues = function(v1, v2) { - // 1. equal primitives - if(v1 === v2) { - return true; - } - - // 2. equal @values - if(_isValue(v1) && _isValue(v2) && - v1['@value'] === v2['@value'] && - v1['@type'] === v2['@type'] && - v1['@language'] === v2['@language'] && - v1['@index'] === v2['@index']) { - return true; - } - - // 3. equal @ids - if(_isObject(v1) && ('@id' in v1) && _isObject(v2) && ('@id' in v2)) { - return v1['@id'] === v2['@id']; - } - - return false; -}; - -/** - * Gets the value for the given active context key and type, null if none is - * set. - * - * @param ctx the active context. - * @param key the context key. - * @param [type] the type of value to get (eg: '@id', '@type'), if not - * specified gets the entire entry for a key, null if not found. - * - * @return the value. - */ -jsonld.getContextValue = function(ctx, key, type) { - var rval = null; - - // return null for invalid key - if(key === null) { - return rval; - } - - // get default language - if(type === '@language' && (type in ctx)) { - rval = ctx[type]; - } - - // get specific entry information - if(ctx.mappings[key]) { - var entry = ctx.mappings[key]; - - if(_isUndefined(type)) { - // return whole entry - rval = entry; - } else if(type in entry) { - // return entry value for type - rval = entry[type]; - } - } - - return rval; -}; - -/** Registered RDF dataset parsers hashed by content-type. */ -var _rdfParsers = {}; - -/** - * Registers an RDF dataset parser by content-type, for use with - * jsonld.fromRDF. An RDF dataset parser will always be given two parameters, - * a string of input and a callback. An RDF dataset parser can be synchronous - * or asynchronous. - * - * If the parser function returns undefined or null then it will be assumed to - * be asynchronous w/a continuation-passing style and the callback parameter - * given to the parser MUST be invoked. - * - * If it returns a Promise, then it will be assumed to be asynchronous, but the - * callback parameter MUST NOT be invoked. It should instead be ignored. - * - * If it returns an RDF dataset, it will be assumed to be synchronous and the - * callback parameter MUST NOT be invoked. It should instead be ignored. - * - * @param contentType the content-type for the parser. - * @param parser(input, callback(err, dataset)) the parser function (takes a - * string as a parameter and either returns null/undefined and uses - * the given callback, returns a Promise, or returns an RDF dataset). - */ -jsonld.registerRDFParser = function(contentType, parser) { - _rdfParsers[contentType] = parser; -}; - -/** - * Unregisters an RDF dataset parser by content-type. - * - * @param contentType the content-type for the parser. - */ -jsonld.unregisterRDFParser = function(contentType) { - delete _rdfParsers[contentType]; -}; - -if(_nodejs) { - // needed for serialization of XML literals - if(typeof XMLSerializer === 'undefined') { - var XMLSerializer = null; - } - if(typeof Node === 'undefined') { - var Node = { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE:12 - }; - } -} - -// constants -var XSD_BOOLEAN = 'http://www.w3.org/2001/XMLSchema#boolean'; -var XSD_DOUBLE = 'http://www.w3.org/2001/XMLSchema#double'; -var XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer'; -var XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string'; - -var RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; -var RDF_LIST = RDF + 'List'; -var RDF_FIRST = RDF + 'first'; -var RDF_REST = RDF + 'rest'; -var RDF_NIL = RDF + 'nil'; -var RDF_TYPE = RDF + 'type'; -var RDF_PLAIN_LITERAL = RDF + 'PlainLiteral'; -var RDF_XML_LITERAL = RDF + 'XMLLiteral'; -var RDF_OBJECT = RDF + 'object'; -var RDF_LANGSTRING = RDF + 'langString'; - -var LINK_HEADER_REL = 'http://www.w3.org/ns/json-ld#context'; -var MAX_CONTEXT_URLS = 10; - -/** - * A JSON-LD Error. - * - * @param msg the error message. - * @param type the error type. - * @param details the error details. - */ -var JsonLdError = function(msg, type, details) { - if(_nodejs) { - Error.call(this); - Error.captureStackTrace(this, this.constructor); - } else if(typeof Error !== 'undefined') { - this.stack = (new Error()).stack; - } - this.name = type || 'jsonld.Error'; - this.message = msg || 'An unspecified JSON-LD error occurred.'; - this.details = details || {}; -}; -if(_nodejs) { - require('util').inherits(JsonLdError, Error); -} else if(typeof Error !== 'undefined') { - JsonLdError.prototype = new Error(); -} - -/** - * Constructs a new JSON-LD Processor. - */ -var Processor = function() {}; - -/** - * Recursively compacts an element using the given active context. All values - * must be in expanded form before this method is called. - * - * @param activeCtx the active context to use. - * @param activeProperty the compacted property associated with the element - * to compact, null for none. - * @param element the element to compact. - * @param options the compaction options. - * - * @return the compacted value. - */ -Processor.prototype.compact = function( - activeCtx, activeProperty, element, options) { - // recursively compact array - if(_isArray(element)) { - var rval = []; - for(var i = 0; i < element.length; ++i) { - // compact, dropping any null values - var compacted = this.compact( - activeCtx, activeProperty, element[i], options); - if(compacted !== null) { - rval.push(compacted); - } - } - if(options.compactArrays && rval.length === 1) { - // use single element if no container is specified - var container = jsonld.getContextValue( - activeCtx, activeProperty, '@container'); - if(container === null) { - rval = rval[0]; - } - } - return rval; - } - - // recursively compact object - if(_isObject(element)) { - if(options.link && '@id' in element && element['@id'] in options.link) { - // check for a linked element to reuse - var linked = options.link[element['@id']]; - for(var i = 0; i < linked.length; ++i) { - if(linked[i].expanded === element) { - return linked[i].compacted; - } - } - } - - // do value compaction on @values and subject references - if(_isValue(element) || _isSubjectReference(element)) { - var rval = _compactValue(activeCtx, activeProperty, element); - if(options.link && _isSubjectReference(element)) { - // store linked element - if(!(element['@id'] in options.link)) { - options.link[element['@id']] = []; - } - options.link[element['@id']].push({expanded: element, compacted: rval}); - } - return rval; - } - - // FIXME: avoid misuse of active property as an expanded property? - var insideReverse = (activeProperty === '@reverse'); - - var rval = {}; - - if(options.link && '@id' in element) { - // store linked element - if(!(element['@id'] in options.link)) { - options.link[element['@id']] = []; - } - options.link[element['@id']].push({expanded: element, compacted: rval}); - } - - // process element keys in order - var keys = Object.keys(element).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var expandedProperty = keys[ki]; - var expandedValue = element[expandedProperty]; - - // compact @id and @type(s) - if(expandedProperty === '@id' || expandedProperty === '@type') { - var compactedValue; - - // compact single @id - if(_isString(expandedValue)) { - compactedValue = _compactIri( - activeCtx, expandedValue, null, - {vocab: (expandedProperty === '@type')}); - } else { - // expanded value must be a @type array - compactedValue = []; - for(var vi = 0; vi < expandedValue.length; ++vi) { - compactedValue.push(_compactIri( - activeCtx, expandedValue[vi], null, {vocab: true})); - } - } - - // use keyword alias and add value - var alias = _compactIri(activeCtx, expandedProperty); - var isArray = (_isArray(compactedValue) && expandedValue.length === 0); - jsonld.addValue( - rval, alias, compactedValue, {propertyIsArray: isArray}); - continue; - } - - // handle @reverse - if(expandedProperty === '@reverse') { - // recursively compact expanded value - var compactedValue = this.compact( - activeCtx, '@reverse', expandedValue, options); - - // handle double-reversed properties - for(var compactedProperty in compactedValue) { - if(activeCtx.mappings[compactedProperty] && - activeCtx.mappings[compactedProperty].reverse) { - var value = compactedValue[compactedProperty]; - var container = jsonld.getContextValue( - activeCtx, compactedProperty, '@container'); - var useArray = (container === '@set' || !options.compactArrays); - jsonld.addValue( - rval, compactedProperty, value, {propertyIsArray: useArray}); - delete compactedValue[compactedProperty]; - } - } - - if(Object.keys(compactedValue).length > 0) { - // use keyword alias and add value - var alias = _compactIri(activeCtx, expandedProperty); - jsonld.addValue(rval, alias, compactedValue); - } - - continue; - } - - // handle @index property - if(expandedProperty === '@index') { - // drop @index if inside an @index container - var container = jsonld.getContextValue( - activeCtx, activeProperty, '@container'); - if(container === '@index') { - continue; - } - - // use keyword alias and add value - var alias = _compactIri(activeCtx, expandedProperty); - jsonld.addValue(rval, alias, expandedValue); - continue; - } - - // skip array processing for keywords that aren't @graph or @list - if(expandedProperty !== '@graph' && expandedProperty !== '@list' && - _isKeyword(expandedProperty)) { - // use keyword alias and add value as is - var alias = _compactIri(activeCtx, expandedProperty); - jsonld.addValue(rval, alias, expandedValue); - continue; - } - - // Note: expanded value must be an array due to expansion algorithm. - - // preserve empty arrays - if(expandedValue.length === 0) { - var itemActiveProperty = _compactIri( - activeCtx, expandedProperty, expandedValue, {vocab: true}, - insideReverse); - jsonld.addValue( - rval, itemActiveProperty, expandedValue, {propertyIsArray: true}); - } - - // recusively process array values - for(var vi = 0; vi < expandedValue.length; ++vi) { - var expandedItem = expandedValue[vi]; - - // compact property and get container type - var itemActiveProperty = _compactIri( - activeCtx, expandedProperty, expandedItem, {vocab: true}, - insideReverse); - var container = jsonld.getContextValue( - activeCtx, itemActiveProperty, '@container'); - - // get @list value if appropriate - var isList = _isList(expandedItem); - var list = null; - if(isList) { - list = expandedItem['@list']; - } - - // recursively compact expanded item - var compactedItem = this.compact( - activeCtx, itemActiveProperty, isList ? list : expandedItem, options); - - // handle @list - if(isList) { - // ensure @list value is an array - if(!_isArray(compactedItem)) { - compactedItem = [compactedItem]; - } - - if(container !== '@list') { - // wrap using @list alias - var wrapper = {}; - wrapper[_compactIri(activeCtx, '@list')] = compactedItem; - compactedItem = wrapper; - - // include @index from expanded @list, if any - if('@index' in expandedItem) { - compactedItem[_compactIri(activeCtx, '@index')] = - expandedItem['@index']; - } - } else if(itemActiveProperty in rval) { - // can't use @list container for more than 1 list - throw new JsonLdError( - 'JSON-LD compact error; property has a "@list" @container ' + - 'rule but there is more than a single @list that matches ' + - 'the compacted term in the document. Compaction might mix ' + - 'unwanted items into the list.', - 'jsonld.SyntaxError', {code: 'compaction to list of lists'}); - } - } - - // handle language and index maps - if(container === '@language' || container === '@index') { - // get or create the map object - var mapObject; - if(itemActiveProperty in rval) { - mapObject = rval[itemActiveProperty]; - } else { - rval[itemActiveProperty] = mapObject = {}; - } - - // if container is a language map, simplify compacted value to - // a simple string - if(container === '@language' && _isValue(compactedItem)) { - compactedItem = compactedItem['@value']; - } - - // add compact value to map object using key from expanded value - // based on the container type - jsonld.addValue(mapObject, expandedItem[container], compactedItem); - } else { - // use an array if: compactArrays flag is false, - // @container is @set or @list , value is an empty - // array, or key is @graph - var isArray = (!options.compactArrays || container === '@set' || - container === '@list' || - (_isArray(compactedItem) && compactedItem.length === 0) || - expandedProperty === '@list' || expandedProperty === '@graph'); - - // add compact value - jsonld.addValue( - rval, itemActiveProperty, compactedItem, - {propertyIsArray: isArray}); - } - } - } - - return rval; - } - - // only primitives remain which are already compact - return element; -}; - -/** - * Recursively expands an element using the given context. Any context in - * the element will be removed. All context URLs must have been retrieved - * before calling this method. - * - * @param activeCtx the context to use. - * @param activeProperty the property for the element, null for none. - * @param element the element to expand. - * @param options the expansion options. - * @param insideList true if the element is a list, false if not. - * - * @return the expanded value. - */ -Processor.prototype.expand = function( - activeCtx, activeProperty, element, options, insideList) { - var self = this; - - // nothing to expand - if(element === null || element === undefined) { - return null; - } - - if(!_isArray(element) && !_isObject(element)) { - // drop free-floating scalars that are not in lists - if(!insideList && (activeProperty === null || - _expandIri(activeCtx, activeProperty, {vocab: true}) === '@graph')) { - return null; - } - - // expand element according to value expansion rules - return _expandValue(activeCtx, activeProperty, element); - } - - // recursively expand array - if(_isArray(element)) { - var rval = []; - var container = jsonld.getContextValue( - activeCtx, activeProperty, '@container'); - insideList = insideList || container === '@list'; - for(var i = 0; i < element.length; ++i) { - // expand element - var e = self.expand(activeCtx, activeProperty, element[i], options); - if(insideList && (_isArray(e) || _isList(e))) { - // lists of lists are illegal - throw new JsonLdError( - 'Invalid JSON-LD syntax; lists of lists are not permitted.', - 'jsonld.SyntaxError', {code: 'list of lists'}); - } - // drop null values - if(e !== null) { - if(_isArray(e)) { - rval = rval.concat(e); - } else { - rval.push(e); - } - } - } - return rval; - } - - // recursively expand object: - - // if element has a context, process it - if('@context' in element) { - activeCtx = self.processContext(activeCtx, element['@context'], options); - } - - // expand the active property - var expandedActiveProperty = _expandIri( - activeCtx, activeProperty, {vocab: true}); - - var rval = {}; - var keys = Object.keys(element).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var key = keys[ki]; - var value = element[key]; - var expandedValue; - - // skip @context - if(key === '@context') { - continue; - } - - // expand property - var expandedProperty = _expandIri(activeCtx, key, {vocab: true}); - - // drop non-absolute IRI keys that aren't keywords - if(expandedProperty === null || - !(_isAbsoluteIri(expandedProperty) || _isKeyword(expandedProperty))) { - continue; - } - - if(_isKeyword(expandedProperty)) { - if(expandedActiveProperty === '@reverse') { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a keyword cannot be used as a @reverse ' + - 'property.', 'jsonld.SyntaxError', - {code: 'invalid reverse property map', value: value}); - } - if(expandedProperty in rval) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; colliding keywords detected.', - 'jsonld.SyntaxError', - {code: 'colliding keywords', keyword: expandedProperty}); - } - } - - // syntax error if @id is not a string - if(expandedProperty === '@id' && !_isString(value)) { - if(!options.isFrame) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@id" value must a string.', - 'jsonld.SyntaxError', {code: 'invalid @id value', value: value}); - } - if(!_isObject(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@id" value must be a string or an ' + - 'object.', 'jsonld.SyntaxError', - {code: 'invalid @id value', value: value}); - } - } - - if(expandedProperty === '@type') { - _validateTypeValue(value); - } - - // @graph must be an array or an object - if(expandedProperty === '@graph' && - !(_isObject(value) || _isArray(value))) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@graph" value must not be an ' + - 'object or an array.', - 'jsonld.SyntaxError', {code: 'invalid @graph value', value: value}); - } - - // @value must not be an object or an array - if(expandedProperty === '@value' && - (_isObject(value) || _isArray(value))) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@value" value must not be an ' + - 'object or an array.', - 'jsonld.SyntaxError', - {code: 'invalid value object value', value: value}); - } - - // @language must be a string - if(expandedProperty === '@language') { - if(!_isString(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@language" value must be a string.', - 'jsonld.SyntaxError', - {code: 'invalid language-tagged string', value: value}); - } - // ensure language value is lowercase - value = value.toLowerCase(); - } - - // @index must be a string - if(expandedProperty === '@index') { - if(!_isString(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@index" value must be a string.', - 'jsonld.SyntaxError', - {code: 'invalid @index value', value: value}); - } - } - - // @reverse must be an object - if(expandedProperty === '@reverse') { - if(!_isObject(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@reverse" value must be an object.', - 'jsonld.SyntaxError', {code: 'invalid @reverse value', value: value}); - } - - expandedValue = self.expand(activeCtx, '@reverse', value, options); - - // properties double-reversed - if('@reverse' in expandedValue) { - for(var property in expandedValue['@reverse']) { - jsonld.addValue( - rval, property, expandedValue['@reverse'][property], - {propertyIsArray: true}); - } - } - - // FIXME: can this be merged with code below to simplify? - // merge in all reversed properties - var reverseMap = rval['@reverse'] || null; - for(var property in expandedValue) { - if(property === '@reverse') { - continue; - } - if(reverseMap === null) { - reverseMap = rval['@reverse'] = {}; - } - jsonld.addValue(reverseMap, property, [], {propertyIsArray: true}); - var items = expandedValue[property]; - for(var ii = 0; ii < items.length; ++ii) { - var item = items[ii]; - if(_isValue(item) || _isList(item)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@reverse" value must not be a ' + - '@value or an @list.', 'jsonld.SyntaxError', - {code: 'invalid reverse property value', value: expandedValue}); - } - jsonld.addValue( - reverseMap, property, item, {propertyIsArray: true}); - } - } - - continue; - } - - var container = jsonld.getContextValue(activeCtx, key, '@container'); - - if(container === '@language' && _isObject(value)) { - // handle language map container (skip if value is not an object) - expandedValue = _expandLanguageMap(value); - } else if(container === '@index' && _isObject(value)) { - // handle index container (skip if value is not an object) - expandedValue = (function _expandIndexMap(activeProperty) { - var rval = []; - var keys = Object.keys(value).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var key = keys[ki]; - var val = value[key]; - if(!_isArray(val)) { - val = [val]; - } - val = self.expand(activeCtx, activeProperty, val, options, false); - for(var vi = 0; vi < val.length; ++vi) { - var item = val[vi]; - if(!('@index' in item)) { - item['@index'] = key; - } - rval.push(item); - } - } - return rval; - })(key); - } else { - // recurse into @list or @set - var isList = (expandedProperty === '@list'); - if(isList || expandedProperty === '@set') { - var nextActiveProperty = activeProperty; - if(isList && expandedActiveProperty === '@graph') { - nextActiveProperty = null; - } - expandedValue = self.expand( - activeCtx, nextActiveProperty, value, options, isList); - if(isList && _isList(expandedValue)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; lists of lists are not permitted.', - 'jsonld.SyntaxError', {code: 'list of lists'}); - } - } else { - // recursively expand value with key as new active property - expandedValue = self.expand(activeCtx, key, value, options, false); - } - } - - // drop null values if property is not @value - if(expandedValue === null && expandedProperty !== '@value') { - continue; - } - - // convert expanded value to @list if container specifies it - if(expandedProperty !== '@list' && !_isList(expandedValue) && - container === '@list') { - // ensure expanded value is an array - expandedValue = (_isArray(expandedValue) ? - expandedValue : [expandedValue]); - expandedValue = {'@list': expandedValue}; - } - - // FIXME: can this be merged with code above to simplify? - // merge in reverse properties - if(activeCtx.mappings[key] && activeCtx.mappings[key].reverse) { - var reverseMap = rval['@reverse'] = rval['@reverse'] || {}; - if(!_isArray(expandedValue)) { - expandedValue = [expandedValue]; - } - for(var ii = 0; ii < expandedValue.length; ++ii) { - var item = expandedValue[ii]; - if(_isValue(item) || _isList(item)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@reverse" value must not be a ' + - '@value or an @list.', 'jsonld.SyntaxError', - {code: 'invalid reverse property value', value: expandedValue}); - } - jsonld.addValue( - reverseMap, expandedProperty, item, {propertyIsArray: true}); - } - continue; - } - - // add value for property - // use an array except for certain keywords - var useArray = - ['@index', '@id', '@type', '@value', '@language'].indexOf( - expandedProperty) === -1; - jsonld.addValue( - rval, expandedProperty, expandedValue, {propertyIsArray: useArray}); - } - - // get property count on expanded output - keys = Object.keys(rval); - var count = keys.length; - - if('@value' in rval) { - // @value must only have @language or @type - if('@type' in rval && '@language' in rval) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an element containing "@value" may not ' + - 'contain both "@type" and "@language".', - 'jsonld.SyntaxError', {code: 'invalid value object', element: rval}); - } - var validCount = count - 1; - if('@type' in rval) { - validCount -= 1; - } - if('@index' in rval) { - validCount -= 1; - } - if('@language' in rval) { - validCount -= 1; - } - if(validCount !== 0) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an element containing "@value" may only ' + - 'have an "@index" property and at most one other property ' + - 'which can be "@type" or "@language".', - 'jsonld.SyntaxError', {code: 'invalid value object', element: rval}); - } - // drop null @values - if(rval['@value'] === null) { - rval = null; - } else if('@language' in rval && !_isString(rval['@value'])) { - // if @language is present, @value must be a string - throw new JsonLdError( - 'Invalid JSON-LD syntax; only strings may be language-tagged.', - 'jsonld.SyntaxError', - {code: 'invalid language-tagged value', element: rval}); - } else if('@type' in rval && (!_isAbsoluteIri(rval['@type']) || - rval['@type'].indexOf('_:') === 0)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an element containing "@value" and "@type" ' + - 'must have an absolute IRI for the value of "@type".', - 'jsonld.SyntaxError', {code: 'invalid typed value', element: rval}); - } - } else if('@type' in rval && !_isArray(rval['@type'])) { - // convert @type to an array - rval['@type'] = [rval['@type']]; - } else if('@set' in rval || '@list' in rval) { - // handle @set and @list - if(count > 1 && !(count === 2 && '@index' in rval)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; if an element has the property "@set" ' + - 'or "@list", then it can have at most one other property that is ' + - '"@index".', 'jsonld.SyntaxError', - {code: 'invalid set or list object', element: rval}); - } - // optimize away @set - if('@set' in rval) { - rval = rval['@set']; - keys = Object.keys(rval); - count = keys.length; - } - } else if(count === 1 && '@language' in rval) { - // drop objects with only @language - rval = null; - } - - // drop certain top-level objects that do not occur in lists - if(_isObject(rval) && - !options.keepFreeFloatingNodes && !insideList && - (activeProperty === null || expandedActiveProperty === '@graph')) { - // drop empty object, top-level @value/@list, or object with only @id - if(count === 0 || '@value' in rval || '@list' in rval || - (count === 1 && '@id' in rval)) { - rval = null; - } - } - - return rval; -}; - -/** - * Creates a JSON-LD node map (node ID => node). - * - * @param input the expanded JSON-LD to create a node map of. - * @param [options] the options to use: - * [namer] the UniqueNamer to use. - * - * @return the node map. - */ -Processor.prototype.createNodeMap = function(input, options) { - options = options || {}; - - // produce a map of all subjects and name each bnode - var namer = options.namer || new UniqueNamer('_:b'); - var graphs = {'@default': {}}; - _createNodeMap(input, graphs, '@default', namer); - - // add all non-default graphs to default graph - return _mergeNodeMaps(graphs); -}; - -/** - * Performs JSON-LD flattening. - * - * @param input the expanded JSON-LD to flatten. - * - * @return the flattened output. - */ -Processor.prototype.flatten = function(input) { - var defaultGraph = this.createNodeMap(input); - - // produce flattened output - var flattened = []; - var keys = Object.keys(defaultGraph).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var node = defaultGraph[keys[ki]]; - // only add full subjects to top-level - if(!_isSubjectReference(node)) { - flattened.push(node); - } - } - return flattened; -}; - -/** - * Performs JSON-LD framing. - * - * @param input the expanded JSON-LD to frame. - * @param frame the expanded JSON-LD frame to use. - * @param options the framing options. - * - * @return the framed output. - */ -Processor.prototype.frame = function(input, frame, options) { - // create framing state - var state = { - options: options, - graphs: {'@default': {}, '@merged': {}}, - subjectStack: [], - link: {} - }; - - // produce a map of all graphs and name each bnode - // FIXME: currently uses subjects from @merged graph only - var namer = new UniqueNamer('_:b'); - _createNodeMap(input, state.graphs, '@merged', namer); - state.subjects = state.graphs['@merged']; - - // frame the subjects - var framed = []; - _frame(state, Object.keys(state.subjects).sort(), frame, framed, null); - return framed; -}; - -/** - * Performs normalization on the given RDF dataset. - * - * @param dataset the RDF dataset to normalize. - * @param options the normalization options. - * @param callback(err, normalized) called once the operation completes. - */ -Processor.prototype.normalize = function(dataset, options, callback) { - // create quads and map bnodes to their associated quads - var quads = []; - var bnodes = {}; - for(var graphName in dataset) { - var triples = dataset[graphName]; - if(graphName === '@default') { - graphName = null; - } - for(var ti = 0; ti < triples.length; ++ti) { - var quad = triples[ti]; - if(graphName !== null) { - if(graphName.indexOf('_:') === 0) { - quad.name = {type: 'blank node', value: graphName}; - } else { - quad.name = {type: 'IRI', value: graphName}; - } - } - quads.push(quad); - - var attrs = ['subject', 'object', 'name']; - for(var ai = 0; ai < attrs.length; ++ai) { - var attr = attrs[ai]; - if(quad[attr] && quad[attr].type === 'blank node') { - var id = quad[attr].value; - if(id in bnodes) { - bnodes[id].quads.push(quad); - } else { - bnodes[id] = {quads: [quad]}; - } - } - } - } - } - - // mapping complete, start canonical naming - var namer = new UniqueNamer('_:c14n'); - return hashBlankNodes(Object.keys(bnodes)); - - // generates unique and duplicate hashes for bnodes - function hashBlankNodes(unnamed) { - var nextUnnamed = []; - var duplicates = {}; - var unique = {}; - - // hash quads for each unnamed bnode - jsonld.setImmediate(function() {hashUnnamed(0);}); - function hashUnnamed(i) { - if(i === unnamed.length) { - // done, name blank nodes - return nameBlankNodes(unique, duplicates, nextUnnamed); - } - - // hash unnamed bnode - var bnode = unnamed[i]; - var hash = _hashQuads(bnode, bnodes); - - // store hash as unique or a duplicate - if(hash in duplicates) { - duplicates[hash].push(bnode); - nextUnnamed.push(bnode); - } else if(hash in unique) { - duplicates[hash] = [unique[hash], bnode]; - nextUnnamed.push(unique[hash]); - nextUnnamed.push(bnode); - delete unique[hash]; - } else { - unique[hash] = bnode; - } - - // hash next unnamed bnode - jsonld.setImmediate(function() {hashUnnamed(i + 1);}); - } - } - - // names unique hash bnodes - function nameBlankNodes(unique, duplicates, unnamed) { - // name unique bnodes in sorted hash order - var named = false; - var hashes = Object.keys(unique).sort(); - for(var i = 0; i < hashes.length; ++i) { - var bnode = unique[hashes[i]]; - namer.getName(bnode); - named = true; - } - - if(named) { - // continue to hash bnodes if a bnode was assigned a name - hashBlankNodes(unnamed); - } else { - // name the duplicate hash bnodes - nameDuplicates(duplicates); - } - } - - // names duplicate hash bnodes - function nameDuplicates(duplicates) { - // enumerate duplicate hash groups in sorted order - var hashes = Object.keys(duplicates).sort(); - - // process each group - processGroup(0); - function processGroup(i) { - if(i === hashes.length) { - // done, create JSON-LD array - return createArray(); - } - - // name each group member - var group = duplicates[hashes[i]]; - var results = []; - nameGroupMember(group, 0); - function nameGroupMember(group, n) { - if(n === group.length) { - // name bnodes in hash order - results.sort(function(a, b) { - a = a.hash; - b = b.hash; - return (a < b) ? -1 : ((a > b) ? 1 : 0); - }); - for(var r in results) { - // name all bnodes in path namer in key-entry order - // Note: key-order is preserved in javascript - for(var key in results[r].pathNamer.existing) { - namer.getName(key); - } - } - return processGroup(i + 1); - } - - // skip already-named bnodes - var bnode = group[n]; - if(namer.isNamed(bnode)) { - return nameGroupMember(group, n + 1); - } - - // hash bnode paths - var pathNamer = new UniqueNamer('_:b'); - pathNamer.getName(bnode); - _hashPaths(bnode, bnodes, namer, pathNamer, - function(err, result) { - if(err) { - return callback(err); - } - results.push(result); - nameGroupMember(group, n + 1); - }); - } - } - } - - // creates the sorted array of RDF quads - function createArray() { - var normalized = []; - - /* Note: At this point all bnodes in the set of RDF quads have been - assigned canonical names, which have been stored in the 'namer' object. - Here each quad is updated by assigning each of its bnodes its new name - via the 'namer' object. */ - - // update bnode names in each quad and serialize - for(var i = 0; i < quads.length; ++i) { - var quad = quads[i]; - var attrs = ['subject', 'object', 'name']; - for(var ai = 0; ai < attrs.length; ++ai) { - var attr = attrs[ai]; - if(quad[attr] && quad[attr].type === 'blank node' && - quad[attr].value.indexOf('_:c14n') !== 0) { - quad[attr].value = namer.getName(quad[attr].value); - } - } - normalized.push(_toNQuad(quad, quad.name ? quad.name.value : null)); - } - - // sort normalized output - normalized.sort(); - - // handle output format - if(options.format) { - if(options.format === 'application/nquads') { - return callback(null, normalized.join('')); - } - return callback(new JsonLdError( - 'Unknown output format.', - 'jsonld.UnknownFormat', {format: options.format})); - } - - // output RDF dataset - callback(null, _parseNQuads(normalized.join(''))); - } -}; - -/** - * Converts an RDF dataset to JSON-LD. - * - * @param dataset the RDF dataset. - * @param options the RDF serialization options. - * @param callback(err, output) called once the operation completes. - */ -Processor.prototype.fromRDF = function(dataset, options, callback) { - var defaultGraph = {}; - var graphMap = {'@default': defaultGraph}; - var referencedOnce = {}; - - for(var name in dataset) { - var graph = dataset[name]; - if(!(name in graphMap)) { - graphMap[name] = {}; - } - if(name !== '@default' && !(name in defaultGraph)) { - defaultGraph[name] = {'@id': name}; - } - var nodeMap = graphMap[name]; - for(var ti = 0; ti < graph.length; ++ti) { - var triple = graph[ti]; - - // get subject, predicate, object - var s = triple.subject.value; - var p = triple.predicate.value; - var o = triple.object; - - if(!(s in nodeMap)) { - nodeMap[s] = {'@id': s}; - } - var node = nodeMap[s]; - - var objectIsId = (o.type === 'IRI' || o.type === 'blank node'); - if(objectIsId && !(o.value in nodeMap)) { - nodeMap[o.value] = {'@id': o.value}; - } - - if(p === RDF_TYPE && !options.useRdfType && objectIsId) { - jsonld.addValue(node, '@type', o.value, {propertyIsArray: true}); - continue; - } - - var value = _RDFToObject(o, options.useNativeTypes); - jsonld.addValue(node, p, value, {propertyIsArray: true}); - - // object may be an RDF list/partial list node but we can't know easily - // until all triples are read - if(objectIsId) { - if(o.value === RDF_NIL) { - // track rdf:nil uniquely per graph - var object = nodeMap[o.value]; - if(!('usages' in object)) { - object.usages = []; - } - object.usages.push({ - node: node, - property: p, - value: value - }); - } else if(o.value in referencedOnce) { - // object referenced more than once - referencedOnce[o.value] = false; - } else { - // keep track of single reference - referencedOnce[o.value] = { - node: node, - property: p, - value: value - }; - } - } - } - } - - // convert linked lists to @list arrays - for(var name in graphMap) { - var graphObject = graphMap[name]; - - // no @lists to be converted, continue - if(!(RDF_NIL in graphObject)) { - continue; - } - - // iterate backwards through each RDF list - var nil = graphObject[RDF_NIL]; - for(var i = 0; i < nil.usages.length; ++i) { - var usage = nil.usages[i]; - var node = usage.node; - var property = usage.property; - var head = usage.value; - var list = []; - var listNodes = []; - - // ensure node is a well-formed list node; it must: - // 1. Be referenced only once. - // 2. Have an array for rdf:first that has 1 item. - // 3. Have an array for rdf:rest that has 1 item. - // 4. Have no keys other than: @id, rdf:first, rdf:rest, and, - // optionally, @type where the value is rdf:List. - var nodeKeyCount = Object.keys(node).length; - while(property === RDF_REST && - _isObject(referencedOnce[node['@id']]) && - _isArray(node[RDF_FIRST]) && node[RDF_FIRST].length === 1 && - _isArray(node[RDF_REST]) && node[RDF_REST].length === 1 && - (nodeKeyCount === 3 || (nodeKeyCount === 4 && _isArray(node['@type']) && - node['@type'].length === 1 && node['@type'][0] === RDF_LIST))) { - list.push(node[RDF_FIRST][0]); - listNodes.push(node['@id']); - - // get next node, moving backwards through list - usage = referencedOnce[node['@id']]; - node = usage.node; - property = usage.property; - head = usage.value; - nodeKeyCount = Object.keys(node).length; - - // if node is not a blank node, then list head found - if(node['@id'].indexOf('_:') !== 0) { - break; - } - } - - // the list is nested in another list - if(property === RDF_FIRST) { - // empty list - if(node['@id'] === RDF_NIL) { - // can't convert rdf:nil to a @list object because it would - // result in a list of lists which isn't supported - continue; - } - - // preserve list head - head = graphObject[head['@id']][RDF_REST][0]; - list.pop(); - listNodes.pop(); - } - - // transform list into @list object - delete head['@id']; - head['@list'] = list.reverse(); - for(var j = 0; j < listNodes.length; ++j) { - delete graphObject[listNodes[j]]; - } - } - - delete nil.usages; - } - - var result = []; - var subjects = Object.keys(defaultGraph).sort(); - for(var i = 0; i < subjects.length; ++i) { - var subject = subjects[i]; - var node = defaultGraph[subject]; - if(subject in graphMap) { - var graph = node['@graph'] = []; - var graphObject = graphMap[subject]; - var subjects_ = Object.keys(graphObject).sort(); - for(var si = 0; si < subjects_.length; ++si) { - var node_ = graphObject[subjects_[si]]; - // only add full subjects to top-level - if(!_isSubjectReference(node_)) { - graph.push(node_); - } - } - } - // only add full subjects to top-level - if(!_isSubjectReference(node)) { - result.push(node); - } - } - - callback(null, result); -}; - -/** - * Outputs an RDF dataset for the expanded JSON-LD input. - * - * @param input the expanded JSON-LD input. - * @param options the RDF serialization options. - * - * @return the RDF dataset. - */ -Processor.prototype.toRDF = function(input, options) { - // create node map for default graph (and any named graphs) - var namer = new UniqueNamer('_:b'); - var nodeMap = {'@default': {}}; - _createNodeMap(input, nodeMap, '@default', namer); - - var dataset = {}; - var graphNames = Object.keys(nodeMap).sort(); - for(var i = 0; i < graphNames.length; ++i) { - var graphName = graphNames[i]; - // skip relative IRIs - if(graphName === '@default' || _isAbsoluteIri(graphName)) { - dataset[graphName] = _graphToRDF(nodeMap[graphName], namer, options); - } - } - return dataset; -}; - -/** - * Processes a local context and returns a new active context. - * - * @param activeCtx the current active context. - * @param localCtx the local context to process. - * @param options the context processing options. - * - * @return the new active context. - */ -Processor.prototype.processContext = function(activeCtx, localCtx, options) { - // normalize local context to an array of @context objects - if(_isObject(localCtx) && '@context' in localCtx && - _isArray(localCtx['@context'])) { - localCtx = localCtx['@context']; - } - var ctxs = _isArray(localCtx) ? localCtx : [localCtx]; - - // no contexts in array, clone existing context - if(ctxs.length === 0) { - return activeCtx.clone(); - } - - // process each context in order, update active context - // on each iteration to ensure proper caching - var rval = activeCtx; - for(var i = 0; i < ctxs.length; ++i) { - var ctx = ctxs[i]; - - // reset to initial context - if(ctx === null) { - rval = activeCtx = _getInitialContext(options); - continue; - } - - // dereference @context key if present - if(_isObject(ctx) && '@context' in ctx) { - ctx = ctx['@context']; - } - - // context must be an object by now, all URLs retrieved before this call - if(!_isObject(ctx)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context must be an object.', - 'jsonld.SyntaxError', {code: 'invalid local context', context: ctx}); - } - - // get context from cache if available - if(jsonld.cache.activeCtx) { - var cached = jsonld.cache.activeCtx.get(activeCtx, ctx); - if(cached) { - rval = activeCtx = cached; - continue; - } - } - - // update active context and clone new one before updating - activeCtx = rval; - rval = rval.clone(); - - // define context mappings for keys in local context - var defined = {}; - - // handle @base - if('@base' in ctx) { - var base = ctx['@base']; - - // clear base - if(base === null) { - base = null; - } else if(!_isString(base)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@base" in a ' + - '@context must be a string or null.', - 'jsonld.SyntaxError', {code: 'invalid base IRI', context: ctx}); - } else if(base !== '' && !_isAbsoluteIri(base)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@base" in a ' + - '@context must be an absolute IRI or the empty string.', - 'jsonld.SyntaxError', {code: 'invalid base IRI', context: ctx}); - } - - if(base !== null) { - base = jsonld.url.parse(base || ''); - } - rval['@base'] = base; - defined['@base'] = true; - } - - // handle @vocab - if('@vocab' in ctx) { - var value = ctx['@vocab']; - if(value === null) { - delete rval['@vocab']; - } else if(!_isString(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + - '@context must be a string or null.', - 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); - } else if(!_isAbsoluteIri(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@vocab" in a ' + - '@context must be an absolute IRI.', - 'jsonld.SyntaxError', {code: 'invalid vocab mapping', context: ctx}); - } else { - rval['@vocab'] = value; - } - defined['@vocab'] = true; - } - - // handle @language - if('@language' in ctx) { - var value = ctx['@language']; - if(value === null) { - delete rval['@language']; - } else if(!_isString(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; the value of "@language" in a ' + - '@context must be a string or null.', - 'jsonld.SyntaxError', - {code: 'invalid default language', context: ctx}); - } else { - rval['@language'] = value.toLowerCase(); - } - defined['@language'] = true; - } - - // process all other keys - for(var key in ctx) { - _createTermDefinition(rval, ctx, key, defined); - } - - // cache result - if(jsonld.cache.activeCtx) { - jsonld.cache.activeCtx.set(activeCtx, ctx, rval); - } - } - - return rval; -}; - -/** - * Expands a language map. - * - * @param languageMap the language map to expand. - * - * @return the expanded language map. - */ -function _expandLanguageMap(languageMap) { - var rval = []; - var keys = Object.keys(languageMap).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var key = keys[ki]; - var val = languageMap[key]; - if(!_isArray(val)) { - val = [val]; - } - for(var vi = 0; vi < val.length; ++vi) { - var item = val[vi]; - if(!_isString(item)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; language map values must be strings.', - 'jsonld.SyntaxError', - {code: 'invalid language map value', languageMap: languageMap}); - } - rval.push({ - '@value': item, - '@language': key.toLowerCase() - }); - } - } - return rval; -} - -/** - * Labels the blank nodes in the given value using the given UniqueNamer. - * - * @param namer the UniqueNamer to use. - * @param element the element with blank nodes to rename. - * - * @return the element. - */ -function _labelBlankNodes(namer, element) { - if(_isArray(element)) { - for(var i = 0; i < element.length; ++i) { - element[i] = _labelBlankNodes(namer, element[i]); - } - } else if(_isList(element)) { - element['@list'] = _labelBlankNodes(namer, element['@list']); - } else if(_isObject(element)) { - // rename blank node - if(_isBlankNode(element)) { - element['@id'] = namer.getName(element['@id']); - } - - // recursively apply to all keys - var keys = Object.keys(element).sort(); - for(var ki = 0; ki < keys.length; ++ki) { - var key = keys[ki]; - if(key !== '@id') { - element[key] = _labelBlankNodes(namer, element[key]); - } - } - } - - return element; -} - -/** - * Expands the given value by using the coercion and keyword rules in the - * given context. - * - * @param activeCtx the active context to use. - * @param activeProperty the active property the value is associated with. - * @param value the value to expand. - * - * @return the expanded value. - */ -function _expandValue(activeCtx, activeProperty, value) { - // nothing to expand - if(value === null || value === undefined) { - return null; - } - - // special-case expand @id and @type (skips '@id' expansion) - var expandedProperty = _expandIri(activeCtx, activeProperty, {vocab: true}); - if(expandedProperty === '@id') { - return _expandIri(activeCtx, value, {base: true}); - } else if(expandedProperty === '@type') { - return _expandIri(activeCtx, value, {vocab: true, base: true}); - } - - // get type definition from context - var type = jsonld.getContextValue(activeCtx, activeProperty, '@type'); - - // do @id expansion (automatic for @graph) - if(type === '@id' || (expandedProperty === '@graph' && _isString(value))) { - return {'@id': _expandIri(activeCtx, value, {base: true})}; - } - // do @id expansion w/vocab - if(type === '@vocab') { - return {'@id': _expandIri(activeCtx, value, {vocab: true, base: true})}; - } - - // do not expand keyword values - if(_isKeyword(expandedProperty)) { - return value; - } - - var rval = {}; - - if(type !== null) { - // other type - rval['@type'] = type; - } else if(_isString(value)) { - // check for language tagging for strings - var language = jsonld.getContextValue( - activeCtx, activeProperty, '@language'); - if(language !== null) { - rval['@language'] = language; - } - } - // do conversion of values that aren't basic JSON types to strings - if(['boolean', 'number', 'string'].indexOf(typeof value) === -1) { - value = value.toString(); - } - rval['@value'] = value; - - return rval; -} - -/** - * Creates an array of RDF triples for the given graph. - * - * @param graph the graph to create RDF triples for. - * @param namer a UniqueNamer for assigning blank node names. - * @param options the RDF serialization options. - * - * @return the array of RDF triples for the given graph. - */ -function _graphToRDF(graph, namer, options) { - var rval = []; - - var ids = Object.keys(graph).sort(); - for(var i = 0; i < ids.length; ++i) { - var id = ids[i]; - var node = graph[id]; - var properties = Object.keys(node).sort(); - for(var pi = 0; pi < properties.length; ++pi) { - var property = properties[pi]; - var items = node[property]; - if(property === '@type') { - property = RDF_TYPE; - } else if(_isKeyword(property)) { - continue; - } - - for(var ii = 0; ii < items.length; ++ii) { - var item = items[ii]; - - // RDF subject - var subject = {}; - subject.type = (id.indexOf('_:') === 0) ? 'blank node' : 'IRI'; - subject.value = id; - - // skip relative IRI subjects - if(!_isAbsoluteIri(id)) { - continue; - } - - // RDF predicate - var predicate = {}; - predicate.type = (property.indexOf('_:') === 0) ? 'blank node' : 'IRI'; - predicate.value = property; - - // skip relative IRI predicates - if(!_isAbsoluteIri(property)) { - continue; - } - - // skip blank node predicates unless producing generalized RDF - if(predicate.type === 'blank node' && !options.produceGeneralizedRdf) { - continue; - } - - // convert @list to triples - if(_isList(item)) { - _listToRDF(item['@list'], namer, subject, predicate, rval); - } else { - // convert value or node object to triple - var object = _objectToRDF(item); - // skip null objects (they are relative IRIs) - if(object) { - rval.push({subject: subject, predicate: predicate, object: object}); - } - } - } - } - } - - return rval; -} - -/** - * Converts a @list value into linked list of blank node RDF triples - * (an RDF collection). - * - * @param list the @list value. - * @param namer a UniqueNamer for assigning blank node names. - * @param subject the subject for the head of the list. - * @param predicate the predicate for the head of the list. - * @param triples the array of triples to append to. - */ -function _listToRDF(list, namer, subject, predicate, triples) { - var first = {type: 'IRI', value: RDF_FIRST}; - var rest = {type: 'IRI', value: RDF_REST}; - var nil = {type: 'IRI', value: RDF_NIL}; - - for(var i = 0; i < list.length; ++i) { - var item = list[i]; - - var blankNode = {type: 'blank node', value: namer.getName()}; - triples.push({subject: subject, predicate: predicate, object: blankNode}); - - subject = blankNode; - predicate = first; - var object = _objectToRDF(item); - - // skip null objects (they are relative IRIs) - if(object) { - triples.push({subject: subject, predicate: predicate, object: object}); - } - - predicate = rest; - } - - triples.push({subject: subject, predicate: predicate, object: nil}); -} - -/** - * Converts a JSON-LD value object to an RDF literal or a JSON-LD string or - * node object to an RDF resource. - * - * @param item the JSON-LD value or node object. - * - * @return the RDF literal or RDF resource. - */ -function _objectToRDF(item) { - var object = {}; - - // convert value object to RDF - if(_isValue(item)) { - object.type = 'literal'; - var value = item['@value']; - var datatype = item['@type'] || null; - - // convert to XSD datatypes as appropriate - if(_isBoolean(value)) { - object.value = value.toString(); - object.datatype = datatype || XSD_BOOLEAN; - } else if(_isDouble(value) || datatype === XSD_DOUBLE) { - if(!_isDouble(value)) { - value = parseFloat(value); - } - // canonical double representation - object.value = value.toExponential(15).replace(/(\d)0*e\+?/, '$1E'); - object.datatype = datatype || XSD_DOUBLE; - } else if(_isNumber(value)) { - object.value = value.toFixed(0); - object.datatype = datatype || XSD_INTEGER; - } else if('@language' in item) { - object.value = value; - object.datatype = datatype || RDF_LANGSTRING; - object.language = item['@language']; - } else { - object.value = value; - object.datatype = datatype || XSD_STRING; - } - } else { - // convert string/node object to RDF - var id = _isObject(item) ? item['@id'] : item; - object.type = (id.indexOf('_:') === 0) ? 'blank node' : 'IRI'; - object.value = id; - } - - // skip relative IRIs - if(object.type === 'IRI' && !_isAbsoluteIri(object.value)) { - return null; - } - - return object; -} - -/** - * Converts an RDF triple object to a JSON-LD object. - * - * @param o the RDF triple object to convert. - * @param useNativeTypes true to output native types, false not to. - * - * @return the JSON-LD object. - */ -function _RDFToObject(o, useNativeTypes) { - // convert IRI/blank node object to JSON-LD - if(o.type === 'IRI' || o.type === 'blank node') { - return {'@id': o.value}; - } - - // convert literal to JSON-LD - var rval = {'@value': o.value}; - - // add language - if(o.language) { - rval['@language'] = o.language; - } else { - var type = o.datatype; - if(!type) { - type = XSD_STRING; - } - // use native types for certain xsd types - if(useNativeTypes) { - if(type === XSD_BOOLEAN) { - if(rval['@value'] === 'true') { - rval['@value'] = true; - } else if(rval['@value'] === 'false') { - rval['@value'] = false; - } - } else if(_isNumeric(rval['@value'])) { - if(type === XSD_INTEGER) { - var i = parseInt(rval['@value'], 10); - if(i.toFixed(0) === rval['@value']) { - rval['@value'] = i; - } - } else if(type === XSD_DOUBLE) { - rval['@value'] = parseFloat(rval['@value']); - } - } - // do not add native type - if([XSD_BOOLEAN, XSD_INTEGER, XSD_DOUBLE, XSD_STRING] - .indexOf(type) === -1) { - rval['@type'] = type; - } - } else if(type !== XSD_STRING) { - rval['@type'] = type; - } - } - - return rval; -} - -/** - * Compares two RDF triples for equality. - * - * @param t1 the first triple. - * @param t2 the second triple. - * - * @return true if the triples are the same, false if not. - */ -function _compareRDFTriples(t1, t2) { - var attrs = ['subject', 'predicate', 'object']; - for(var i = 0; i < attrs.length; ++i) { - var attr = attrs[i]; - if(t1[attr].type !== t2[attr].type || t1[attr].value !== t2[attr].value) { - return false; - } - } - if(t1.object.language !== t2.object.language) { - return false; - } - if(t1.object.datatype !== t2.object.datatype) { - return false; - } - return true; -} - -/** - * Hashes all of the quads about a blank node. - * - * @param id the ID of the bnode to hash quads for. - * @param bnodes the mapping of bnodes to quads. - * - * @return the new hash. - */ -function _hashQuads(id, bnodes) { - // return cached hash - if('hash' in bnodes[id]) { - return bnodes[id].hash; - } - - // serialize all of bnode's quads - var quads = bnodes[id].quads; - var nquads = []; - for(var i = 0; i < quads.length; ++i) { - nquads.push(_toNQuad( - quads[i], quads[i].name ? quads[i].name.value : null, id)); - } - // sort serialized quads - nquads.sort(); - // return hashed quads - var hash = bnodes[id].hash = sha1.hash(nquads); - return hash; -} - -/** - * Produces a hash for the paths of adjacent bnodes for a bnode, - * incorporating all information about its subgraph of bnodes. This - * method will recursively pick adjacent bnode permutations that produce the - * lexicographically-least 'path' serializations. - * - * @param id the ID of the bnode to hash paths for. - * @param bnodes the map of bnode quads. - * @param namer the canonical bnode namer. - * @param pathNamer the namer used to assign names to adjacent bnodes. - * @param callback(err, result) called once the operation completes. - */ -function _hashPaths(id, bnodes, namer, pathNamer, callback) { - // create SHA-1 digest - var md = sha1.create(); - - // group adjacent bnodes by hash, keep properties and references separate - var groups = {}; - var groupHashes; - var quads = bnodes[id].quads; - jsonld.setImmediate(function() {groupNodes(0);}); - function groupNodes(i) { - if(i === quads.length) { - // done, hash groups - groupHashes = Object.keys(groups).sort(); - return hashGroup(0); - } - - // get adjacent bnode - var quad = quads[i]; - var bnode = _getAdjacentBlankNodeName(quad.subject, id); - var direction = null; - if(bnode !== null) { - // normal property - direction = 'p'; - } else { - bnode = _getAdjacentBlankNodeName(quad.object, id); - if(bnode !== null) { - // reverse property - direction = 'r'; - } - } - - if(bnode !== null) { - // get bnode name (try canonical, path, then hash) - var name; - if(namer.isNamed(bnode)) { - name = namer.getName(bnode); - } else if(pathNamer.isNamed(bnode)) { - name = pathNamer.getName(bnode); - } else { - name = _hashQuads(bnode, bnodes); - } - - // hash direction, property, and bnode name/hash - var md = sha1.create(); - md.update(direction); - md.update(quad.predicate.value); - md.update(name); - var groupHash = md.digest(); - - // add bnode to hash group - if(groupHash in groups) { - groups[groupHash].push(bnode); - } else { - groups[groupHash] = [bnode]; - } - } - - jsonld.setImmediate(function() {groupNodes(i + 1);}); - } - - // hashes a group of adjacent bnodes - function hashGroup(i) { - if(i === groupHashes.length) { - // done, return SHA-1 digest and path namer - return callback(null, {hash: md.digest(), pathNamer: pathNamer}); - } - - // digest group hash - var groupHash = groupHashes[i]; - md.update(groupHash); - - // choose a path and namer from the permutations - var chosenPath = null; - var chosenNamer = null; - var permutator = new Permutator(groups[groupHash]); - jsonld.setImmediate(function() {permutate();}); - function permutate() { - var permutation = permutator.next(); - var pathNamerCopy = pathNamer.clone(); - - // build adjacent path - var path = ''; - var recurse = []; - for(var n in permutation) { - var bnode = permutation[n]; - - // use canonical name if available - if(namer.isNamed(bnode)) { - path += namer.getName(bnode); - } else { - // recurse if bnode isn't named in the path yet - if(!pathNamerCopy.isNamed(bnode)) { - recurse.push(bnode); - } - path += pathNamerCopy.getName(bnode); - } - - // skip permutation if path is already >= chosen path - if(chosenPath !== null && path.length >= chosenPath.length && - path > chosenPath) { - return nextPermutation(true); - } - } - - // does the next recursion - nextRecursion(0); - function nextRecursion(n) { - if(n === recurse.length) { - // done, do next permutation - return nextPermutation(false); - } - - // do recursion - var bnode = recurse[n]; - _hashPaths(bnode, bnodes, namer, pathNamerCopy, - function(err, result) { - if(err) { - return callback(err); - } - path += pathNamerCopy.getName(bnode) + '<' + result.hash + '>'; - pathNamerCopy = result.pathNamer; - - // skip permutation if path is already >= chosen path - if(chosenPath !== null && path.length >= chosenPath.length && - path > chosenPath) { - return nextPermutation(true); - } - - // do next recursion - nextRecursion(n + 1); - }); - } - - // stores the results of this permutation and runs the next - function nextPermutation(skipped) { - if(!skipped && (chosenPath === null || path < chosenPath)) { - chosenPath = path; - chosenNamer = pathNamerCopy; - } - - // do next permutation - if(permutator.hasNext()) { - jsonld.setImmediate(function() {permutate();}); - } else { - // digest chosen path and update namer - md.update(chosenPath); - pathNamer = chosenNamer; - - // hash the next group - hashGroup(i + 1); - } - } - } - } -} - -/** - * A helper function that gets the blank node name from an RDF quad node - * (subject or object). If the node is a blank node and its value - * does not match the given blank node ID, it will be returned. - * - * @param node the RDF quad node. - * @param id the ID of the blank node to look next to. - * - * @return the adjacent blank node name or null if none was found. - */ -function _getAdjacentBlankNodeName(node, id) { - return (node.type === 'blank node' && node.value !== id ? node.value : null); -} - -/** - * Recursively flattens the subjects in the given JSON-LD expanded input - * into a node map. - * - * @param input the JSON-LD expanded input. - * @param graphs a map of graph name to subject map. - * @param graph the name of the current graph. - * @param namer the blank node namer. - * @param name the name assigned to the current input if it is a bnode. - * @param list the list to append to, null for none. - */ -function _createNodeMap(input, graphs, graph, namer, name, list) { - // recurse through array - if(_isArray(input)) { - for(var i = 0; i < input.length; ++i) { - _createNodeMap(input[i], graphs, graph, namer, undefined, list); - } - return; - } - - // add non-object to list - if(!_isObject(input)) { - if(list) { - list.push(input); - } - return; - } - - // add values to list - if(_isValue(input)) { - if('@type' in input) { - var type = input['@type']; - // rename @type blank node - if(type.indexOf('_:') === 0) { - input['@type'] = type = namer.getName(type); - } - } - if(list) { - list.push(input); - } - return; - } - - // Note: At this point, input must be a subject. - - // spec requires @type to be named first, so assign names early - if('@type' in input) { - var types = input['@type']; - for(var i = 0; i < types.length; ++i) { - var type = types[i]; - if(type.indexOf('_:') === 0) { - namer.getName(type); - } - } - } - - // get name for subject - if(_isUndefined(name)) { - name = _isBlankNode(input) ? namer.getName(input['@id']) : input['@id']; - } - - // add subject reference to list - if(list) { - list.push({'@id': name}); - } - - // create new subject or merge into existing one - var subjects = graphs[graph]; - var subject = subjects[name] = subjects[name] || {}; - subject['@id'] = name; - var properties = Object.keys(input).sort(); - for(var pi = 0; pi < properties.length; ++pi) { - var property = properties[pi]; - - // skip @id - if(property === '@id') { - continue; - } - - // handle reverse properties - if(property === '@reverse') { - var referencedNode = {'@id': name}; - var reverseMap = input['@reverse']; - for(var reverseProperty in reverseMap) { - var items = reverseMap[reverseProperty]; - for(var ii = 0; ii < items.length; ++ii) { - var item = items[ii]; - var itemName = item['@id']; - if(_isBlankNode(item)) { - itemName = namer.getName(itemName); - } - _createNodeMap(item, graphs, graph, namer, itemName); - jsonld.addValue( - subjects[itemName], reverseProperty, referencedNode, - {propertyIsArray: true, allowDuplicate: false}); - } - } - continue; - } - - // recurse into graph - if(property === '@graph') { - // add graph subjects map entry - if(!(name in graphs)) { - graphs[name] = {}; - } - var g = (graph === '@merged') ? graph : name; - _createNodeMap(input[property], graphs, g, namer); - continue; - } - - // copy non-@type keywords - if(property !== '@type' && _isKeyword(property)) { - if(property === '@index' && '@index' in subject) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; conflicting @index property detected.', - 'jsonld.SyntaxError', - {code: 'conflicting indexes', subject: subject}); - } - subject[property] = input[property]; - continue; - } - - // iterate over objects - var objects = input[property]; - - // if property is a bnode, assign it a new id - if(property.indexOf('_:') === 0) { - property = namer.getName(property); - } - - // ensure property is added for empty arrays - if(objects.length === 0) { - jsonld.addValue(subject, property, [], {propertyIsArray: true}); - continue; - } - for(var oi = 0; oi < objects.length; ++oi) { - var o = objects[oi]; - - if(property === '@type') { - // rename @type blank nodes - o = (o.indexOf('_:') === 0) ? namer.getName(o) : o; - } - - // handle embedded subject or subject reference - if(_isSubject(o) || _isSubjectReference(o)) { - // rename blank node @id - var id = _isBlankNode(o) ? namer.getName(o['@id']) : o['@id']; - - // add reference and recurse - jsonld.addValue( - subject, property, {'@id': id}, - {propertyIsArray: true, allowDuplicate: false}); - _createNodeMap(o, graphs, graph, namer, id); - } else if(_isList(o)) { - // handle @list - var _list = []; - _createNodeMap(o['@list'], graphs, graph, namer, name, _list); - o = {'@list': _list}; - jsonld.addValue( - subject, property, o, - {propertyIsArray: true, allowDuplicate: false}); - } else { - // handle @value - _createNodeMap(o, graphs, graph, namer, name); - jsonld.addValue( - subject, property, o, {propertyIsArray: true, allowDuplicate: false}); - } - } - } -} - -function _mergeNodeMaps(graphs) { - // add all non-default graphs to default graph - var defaultGraph = graphs['@default']; - var graphNames = Object.keys(graphs).sort(); - for(var i = 0; i < graphNames.length; ++i) { - var graphName = graphNames[i]; - if(graphName === '@default') { - continue; - } - var nodeMap = graphs[graphName]; - var subject = defaultGraph[graphName]; - if(!subject) { - defaultGraph[graphName] = subject = { - '@id': graphName, - '@graph': [] - }; - } else if(!('@graph' in subject)) { - subject['@graph'] = []; - } - var graph = subject['@graph']; - var ids = Object.keys(nodeMap).sort(); - for(var ii = 0; ii < ids.length; ++ii) { - var node = nodeMap[ids[ii]]; - // only add full subjects - if(!_isSubjectReference(node)) { - graph.push(node); - } - } - } - return defaultGraph; -} - -/** - * Frames subjects according to the given frame. - * - * @param state the current framing state. - * @param subjects the subjects to filter. - * @param frame the frame. - * @param parent the parent subject or top-level array. - * @param property the parent property, initialized to null. - */ -function _frame(state, subjects, frame, parent, property) { - // validate the frame - _validateFrame(frame); - frame = frame[0]; - - // get flags for current frame - var options = state.options; - var flags = { - embed: _getFrameFlag(frame, options, 'embed'), - explicit: _getFrameFlag(frame, options, 'explicit'), - requireAll: _getFrameFlag(frame, options, 'requireAll') - }; - - // filter out subjects that match the frame - var matches = _filterSubjects(state, subjects, frame, flags); - - // add matches to output - var ids = Object.keys(matches).sort(); - for(var idx in ids) { - var id = ids[idx]; - var subject = matches[id]; - - if(flags.embed === '@link' && id in state.link) { - // TODO: may want to also match an existing linked subject against - // the current frame ... so different frames could produce different - // subjects that are only shared in-memory when the frames are the same - - // add existing linked subject - _addFrameOutput(parent, property, state.link[id]); - continue; - } - - /* Note: In order to treat each top-level match as a compartmentalized - result, clear the unique embedded subjects map when the property is null, - which only occurs at the top-level. */ - if(property === null) { - state.uniqueEmbeds = {}; - } - - // start output for subject - var output = {}; - output['@id'] = id; - state.link[id] = output; - - // if embed is @never or if a circular reference would be created by an - // embed, the subject cannot be embedded, just add the reference; - // note that a circular reference won't occur when the embed flag is - // `@link` as the above check will short-circuit before reaching this point - if(flags.embed === '@never' || - _createsCircularReference(subject, state.subjectStack)) { - _addFrameOutput(parent, property, output); - continue; - } - - // if only the last match should be embedded - if(flags.embed === '@last') { - // remove any existing embed - if(id in state.uniqueEmbeds) { - _removeEmbed(state, id); - } - state.uniqueEmbeds[id] = {parent: parent, property: property}; - } - - // push matching subject onto stack to enable circular embed checks - state.subjectStack.push(subject); - - // iterate over subject properties - var props = Object.keys(subject).sort(); - for(var i = 0; i < props.length; i++) { - var prop = props[i]; - - // copy keywords to output - if(_isKeyword(prop)) { - output[prop] = _clone(subject[prop]); - continue; - } - - // explicit is on and property isn't in the frame, skip processing - if(flags.explicit && !(prop in frame)) { - continue; - } - - // add objects - var objects = subject[prop]; - for(var oi = 0; oi < objects.length; ++oi) { - var o = objects[oi]; - - // recurse into list - if(_isList(o)) { - // add empty list - var list = {'@list': []}; - _addFrameOutput(output, prop, list); - - // add list objects - var src = o['@list']; - for(var n in src) { - o = src[n]; - if(_isSubjectReference(o)) { - var subframe = (prop in frame ? - frame[prop][0]['@list'] : _createImplicitFrame(flags)); - // recurse into subject reference - _frame(state, [o['@id']], subframe, list, '@list'); - } else { - // include other values automatically - _addFrameOutput(list, '@list', _clone(o)); - } - } - continue; - } - - if(_isSubjectReference(o)) { - // recurse into subject reference - var subframe = (prop in frame ? - frame[prop] : _createImplicitFrame(flags)); - _frame(state, [o['@id']], subframe, output, prop); - } else { - // include other values automatically - _addFrameOutput(output, prop, _clone(o)); - } - } - } - - // handle defaults - var props = Object.keys(frame).sort(); - for(var i = 0; i < props.length; ++i) { - var prop = props[i]; - - // skip keywords - if(_isKeyword(prop)) { - continue; - } - - // if omit default is off, then include default values for properties - // that appear in the next frame but are not in the matching subject - var next = frame[prop][0]; - var omitDefaultOn = _getFrameFlag(next, options, 'omitDefault'); - if(!omitDefaultOn && !(prop in output)) { - var preserve = '@null'; - if('@default' in next) { - preserve = _clone(next['@default']); - } - if(!_isArray(preserve)) { - preserve = [preserve]; - } - output[prop] = [{'@preserve': preserve}]; - } - } - - // add output to parent - _addFrameOutput(parent, property, output); - - // pop matching subject from circular ref-checking stack - state.subjectStack.pop(); - } -} - -/** - * Creates an implicit frame when recursing through subject matches. If - * a frame doesn't have an explicit frame for a particular property, then - * a wildcard child frame will be created that uses the same flags that the - * parent frame used. - * - * @param flags the current framing flags. - * - * @return the implicit frame. - */ -function _createImplicitFrame(flags) { - var frame = {}; - for(var key in flags) { - if(flags[key] !== undefined) { - frame['@' + key] = [flags[key]]; - } - } - return [frame]; -} - -/** - * Checks the current subject stack to see if embedding the given subject - * would cause a circular reference. - * - * @param subjectToEmbed the subject to embed. - * @param subjectStack the current stack of subjects. - * - * @return true if a circular reference would be created, false if not. - */ -function _createsCircularReference(subjectToEmbed, subjectStack) { - for(var i = subjectStack.length - 1; i >= 0; --i) { - if(subjectStack[i]['@id'] === subjectToEmbed['@id']) { - return true; - } - } - return false; -} - -/** - * Gets the frame flag value for the given flag name. - * - * @param frame the frame. - * @param options the framing options. - * @param name the flag name. - * - * @return the flag value. - */ -function _getFrameFlag(frame, options, name) { - var flag = '@' + name; - var rval = (flag in frame ? frame[flag][0] : options[name]); - if(name === 'embed') { - // default is "@last" - // backwards-compatibility support for "embed" maps: - // true => "@last" - // false => "@never" - if(rval === true) { - rval = '@last'; - } else if(rval === false) { - rval = '@never'; - } else if(rval !== '@always' && rval !== '@never' && rval !== '@link') { - rval = '@last'; - } - } - return rval; -} - -/** - * Validates a JSON-LD frame, throwing an exception if the frame is invalid. - * - * @param frame the frame to validate. - */ -function _validateFrame(frame) { - if(!_isArray(frame) || frame.length !== 1 || !_isObject(frame[0])) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a JSON-LD frame must be a single object.', - 'jsonld.SyntaxError', {frame: frame}); - } -} - -/** - * Returns a map of all of the subjects that match a parsed frame. - * - * @param state the current framing state. - * @param subjects the set of subjects to filter. - * @param frame the parsed frame. - * @param flags the frame flags. - * - * @return all of the matched subjects. - */ -function _filterSubjects(state, subjects, frame, flags) { - // filter subjects in @id order - var rval = {}; - for(var i = 0; i < subjects.length; ++i) { - var id = subjects[i]; - var subject = state.subjects[id]; - if(_filterSubject(subject, frame, flags)) { - rval[id] = subject; - } - } - return rval; -} - -/** - * Returns true if the given subject matches the given frame. - * - * @param subject the subject to check. - * @param frame the frame to check. - * @param flags the frame flags. - * - * @return true if the subject matches, false if not. - */ -function _filterSubject(subject, frame, flags) { - // check @type (object value means 'any' type, fall through to ducktyping) - if('@type' in frame && - !(frame['@type'].length === 1 && _isObject(frame['@type'][0]))) { - var types = frame['@type']; - for(var i = 0; i < types.length; ++i) { - // any matching @type is a match - if(jsonld.hasValue(subject, '@type', types[i])) { - return true; - } - } - return false; - } - - // check ducktype - var wildcard = true; - var matchesSome = false; - for(var key in frame) { - if(_isKeyword(key)) { - // skip non-@id and non-@type - if(key !== '@id' && key !== '@type') { - continue; - } - wildcard = false; - - // check @id for a specific @id value - if(key === '@id' && _isString(frame[key])) { - if(subject[key] !== frame[key]) { - return false; - } - matchesSome = true; - continue; - } - } - - wildcard = false; - - if(key in subject) { - // frame[key] === [] means do not match if property is present - if(_isArray(frame[key]) && frame[key].length === 0 && - subject[key] !== undefined) { - return false; - } - matchesSome = true; - continue; - } - - // all properties must match to be a duck unless a @default is specified - var hasDefault = (_isArray(frame[key]) && _isObject(frame[key][0]) && - '@default' in frame[key][0]); - if(flags.requireAll && !hasDefault) { - return false; - } - } - - // return true if wildcard or subject matches some properties - return wildcard || matchesSome; -} - -/** - * Removes an existing embed. - * - * @param state the current framing state. - * @param id the @id of the embed to remove. - */ -function _removeEmbed(state, id) { - // get existing embed - var embeds = state.uniqueEmbeds; - var embed = embeds[id]; - var parent = embed.parent; - var property = embed.property; - - // create reference to replace embed - var subject = {'@id': id}; - - // remove existing embed - if(_isArray(parent)) { - // replace subject with reference - for(var i = 0; i < parent.length; ++i) { - if(jsonld.compareValues(parent[i], subject)) { - parent[i] = subject; - break; - } - } - } else { - // replace subject with reference - var useArray = _isArray(parent[property]); - jsonld.removeValue(parent, property, subject, {propertyIsArray: useArray}); - jsonld.addValue(parent, property, subject, {propertyIsArray: useArray}); - } - - // recursively remove dependent dangling embeds - var removeDependents = function(id) { - // get embed keys as a separate array to enable deleting keys in map - var ids = Object.keys(embeds); - for(var i = 0; i < ids.length; ++i) { - var next = ids[i]; - if(next in embeds && _isObject(embeds[next].parent) && - embeds[next].parent['@id'] === id) { - delete embeds[next]; - removeDependents(next); - } - } - }; - removeDependents(id); -} - -/** - * Adds framing output to the given parent. - * - * @param parent the parent to add to. - * @param property the parent property. - * @param output the output to add. - */ -function _addFrameOutput(parent, property, output) { - if(_isObject(parent)) { - jsonld.addValue(parent, property, output, {propertyIsArray: true}); - } else { - parent.push(output); - } -} - -/** - * Removes the @preserve keywords as the last step of the framing algorithm. - * - * @param ctx the active context used to compact the input. - * @param input the framed, compacted output. - * @param options the compaction options used. - * - * @return the resulting output. - */ -function _removePreserve(ctx, input, options) { - // recurse through arrays - if(_isArray(input)) { - var output = []; - for(var i = 0; i < input.length; ++i) { - var result = _removePreserve(ctx, input[i], options); - // drop nulls from arrays - if(result !== null) { - output.push(result); - } - } - input = output; - } else if(_isObject(input)) { - // remove @preserve - if('@preserve' in input) { - if(input['@preserve'] === '@null') { - return null; - } - return input['@preserve']; - } - - // skip @values - if(_isValue(input)) { - return input; - } - - // recurse through @lists - if(_isList(input)) { - input['@list'] = _removePreserve(ctx, input['@list'], options); - return input; - } - - // handle in-memory linked nodes - var idAlias = _compactIri(ctx, '@id'); - if(idAlias in input) { - var id = input[idAlias]; - if(id in options.link) { - var idx = options.link[id].indexOf(input); - if(idx === -1) { - // prevent circular visitation - options.link[id].push(input); - } else { - // already visited - return options.link[id][idx]; - } - } else { - // prevent circular visitation - options.link[id] = [input]; - } - } - - // recurse through properties - for(var prop in input) { - var result = _removePreserve(ctx, input[prop], options); - var container = jsonld.getContextValue(ctx, prop, '@container'); - if(options.compactArrays && _isArray(result) && result.length === 1 && - container === null) { - result = result[0]; - } - input[prop] = result; - } - } - return input; -} - -/** - * Compares two strings first based on length and then lexicographically. - * - * @param a the first string. - * @param b the second string. - * - * @return -1 if a < b, 1 if a > b, 0 if a == b. - */ -function _compareShortestLeast(a, b) { - if(a.length < b.length) { - return -1; - } - if(b.length < a.length) { - return 1; - } - if(a === b) { - return 0; - } - return (a < b) ? -1 : 1; -} - -/** - * Picks the preferred compaction term from the given inverse context entry. - * - * @param activeCtx the active context. - * @param iri the IRI to pick the term for. - * @param value the value to pick the term for. - * @param containers the preferred containers. - * @param typeOrLanguage either '@type' or '@language'. - * @param typeOrLanguageValue the preferred value for '@type' or '@language'. - * - * @return the preferred term. - */ -function _selectTerm( - activeCtx, iri, value, containers, typeOrLanguage, typeOrLanguageValue) { - if(typeOrLanguageValue === null) { - typeOrLanguageValue = '@null'; - } - - // preferences for the value of @type or @language - var prefs = []; - - // determine prefs for @id based on whether or not value compacts to a term - if((typeOrLanguageValue === '@id' || typeOrLanguageValue === '@reverse') && - _isSubjectReference(value)) { - // prefer @reverse first - if(typeOrLanguageValue === '@reverse') { - prefs.push('@reverse'); - } - // try to compact value to a term - var term = _compactIri(activeCtx, value['@id'], null, {vocab: true}); - if(term in activeCtx.mappings && - activeCtx.mappings[term] && - activeCtx.mappings[term]['@id'] === value['@id']) { - // prefer @vocab - prefs.push.apply(prefs, ['@vocab', '@id']); - } else { - // prefer @id - prefs.push.apply(prefs, ['@id', '@vocab']); - } - } else { - prefs.push(typeOrLanguageValue); - } - prefs.push('@none'); - - var containerMap = activeCtx.inverse[iri]; - for(var ci = 0; ci < containers.length; ++ci) { - // if container not available in the map, continue - var container = containers[ci]; - if(!(container in containerMap)) { - continue; - } - - var typeOrLanguageValueMap = containerMap[container][typeOrLanguage]; - for(var pi = 0; pi < prefs.length; ++pi) { - // if type/language option not available in the map, continue - var pref = prefs[pi]; - if(!(pref in typeOrLanguageValueMap)) { - continue; - } - - // select term - return typeOrLanguageValueMap[pref]; - } - } - - return null; -} - -/** - * Compacts an IRI or keyword into a term or prefix if it can be. If the - * IRI has an associated value it may be passed. - * - * @param activeCtx the active context to use. - * @param iri the IRI to compact. - * @param value the value to check or null. - * @param relativeTo options for how to compact IRIs: - * vocab: true to split after @vocab, false not to. - * @param reverse true if a reverse property is being compacted, false if not. - * - * @return the compacted term, prefix, keyword alias, or the original IRI. - */ -function _compactIri(activeCtx, iri, value, relativeTo, reverse) { - // can't compact null - if(iri === null) { - return iri; - } - - // default value and parent to null - if(_isUndefined(value)) { - value = null; - } - // default reverse to false - if(_isUndefined(reverse)) { - reverse = false; - } - relativeTo = relativeTo || {}; - - // if term is a keyword, default vocab to true - if(_isKeyword(iri)) { - relativeTo.vocab = true; - } - - // use inverse context to pick a term if iri is relative to vocab - if(relativeTo.vocab && iri in activeCtx.getInverse()) { - var defaultLanguage = activeCtx['@language'] || '@none'; - - // prefer @index if available in value - var containers = []; - if(_isObject(value) && '@index' in value) { - containers.push('@index'); - } - - // defaults for term selection based on type/language - var typeOrLanguage = '@language'; - var typeOrLanguageValue = '@null'; - - if(reverse) { - typeOrLanguage = '@type'; - typeOrLanguageValue = '@reverse'; - containers.push('@set'); - } else if(_isList(value)) { - // choose the most specific term that works for all elements in @list - // only select @list containers if @index is NOT in value - if(!('@index' in value)) { - containers.push('@list'); - } - var list = value['@list']; - var commonLanguage = (list.length === 0) ? defaultLanguage : null; - var commonType = null; - for(var i = 0; i < list.length; ++i) { - var item = list[i]; - var itemLanguage = '@none'; - var itemType = '@none'; - if(_isValue(item)) { - if('@language' in item) { - itemLanguage = item['@language']; - } else if('@type' in item) { - itemType = item['@type']; - } else { - // plain literal - itemLanguage = '@null'; - } - } else { - itemType = '@id'; - } - if(commonLanguage === null) { - commonLanguage = itemLanguage; - } else if(itemLanguage !== commonLanguage && _isValue(item)) { - commonLanguage = '@none'; - } - if(commonType === null) { - commonType = itemType; - } else if(itemType !== commonType) { - commonType = '@none'; - } - // there are different languages and types in the list, so choose - // the most generic term, no need to keep iterating the list - if(commonLanguage === '@none' && commonType === '@none') { - break; - } - } - commonLanguage = commonLanguage || '@none'; - commonType = commonType || '@none'; - if(commonType !== '@none') { - typeOrLanguage = '@type'; - typeOrLanguageValue = commonType; - } else { - typeOrLanguageValue = commonLanguage; - } - } else { - if(_isValue(value)) { - if('@language' in value && !('@index' in value)) { - containers.push('@language'); - typeOrLanguageValue = value['@language']; - } else if('@type' in value) { - typeOrLanguage = '@type'; - typeOrLanguageValue = value['@type']; - } - } else { - typeOrLanguage = '@type'; - typeOrLanguageValue = '@id'; - } - containers.push('@set'); - } - - // do term selection - containers.push('@none'); - var term = _selectTerm( - activeCtx, iri, value, containers, typeOrLanguage, typeOrLanguageValue); - if(term !== null) { - return term; - } - } - - // no term match, use @vocab if available - if(relativeTo.vocab) { - if('@vocab' in activeCtx) { - // determine if vocab is a prefix of the iri - var vocab = activeCtx['@vocab']; - if(iri.indexOf(vocab) === 0 && iri !== vocab) { - // use suffix as relative iri if it is not a term in the active context - var suffix = iri.substr(vocab.length); - if(!(suffix in activeCtx.mappings)) { - return suffix; - } - } - } - } - - // no term or @vocab match, check for possible CURIEs - var choice = null; - for(var term in activeCtx.mappings) { - // skip terms with colons, they can't be prefixes - if(term.indexOf(':') !== -1) { - continue; - } - // skip entries with @ids that are not partial matches - var definition = activeCtx.mappings[term]; - if(!definition || - definition['@id'] === iri || iri.indexOf(definition['@id']) !== 0) { - continue; - } - - // a CURIE is usable if: - // 1. it has no mapping, OR - // 2. value is null, which means we're not compacting an @value, AND - // the mapping matches the IRI) - var curie = term + ':' + iri.substr(definition['@id'].length); - var isUsableCurie = (!(curie in activeCtx.mappings) || - (value === null && activeCtx.mappings[curie] && - activeCtx.mappings[curie]['@id'] === iri)); - - // select curie if it is shorter or the same length but lexicographically - // less than the current choice - if(isUsableCurie && (choice === null || - _compareShortestLeast(curie, choice) < 0)) { - choice = curie; - } - } - - // return chosen curie - if(choice !== null) { - return choice; - } - - // compact IRI relative to base - if(!relativeTo.vocab) { - return _removeBase(activeCtx['@base'], iri); - } - - // return IRI as is - return iri; -} - -/** - * Performs value compaction on an object with '@value' or '@id' as the only - * property. - * - * @param activeCtx the active context. - * @param activeProperty the active property that points to the value. - * @param value the value to compact. - * - * @return the compaction result. - */ -function _compactValue(activeCtx, activeProperty, value) { - // value is a @value - if(_isValue(value)) { - // get context rules - var type = jsonld.getContextValue(activeCtx, activeProperty, '@type'); - var language = jsonld.getContextValue( - activeCtx, activeProperty, '@language'); - var container = jsonld.getContextValue( - activeCtx, activeProperty, '@container'); - - // whether or not the value has an @index that must be preserved - var preserveIndex = (('@index' in value) && - container !== '@index'); - - // if there's no @index to preserve ... - if(!preserveIndex) { - // matching @type or @language specified in context, compact value - if(value['@type'] === type || value['@language'] === language) { - return value['@value']; - } - } - - // return just the value of @value if all are true: - // 1. @value is the only key or @index isn't being preserved - // 2. there is no default language or @value is not a string or - // the key has a mapping with a null @language - var keyCount = Object.keys(value).length; - var isValueOnlyKey = (keyCount === 1 || - (keyCount === 2 && ('@index' in value) && !preserveIndex)); - var hasDefaultLanguage = ('@language' in activeCtx); - var isValueString = _isString(value['@value']); - var hasNullMapping = (activeCtx.mappings[activeProperty] && - activeCtx.mappings[activeProperty]['@language'] === null); - if(isValueOnlyKey && - (!hasDefaultLanguage || !isValueString || hasNullMapping)) { - return value['@value']; - } - - var rval = {}; - - // preserve @index - if(preserveIndex) { - rval[_compactIri(activeCtx, '@index')] = value['@index']; - } - - if('@type' in value) { - // compact @type IRI - rval[_compactIri(activeCtx, '@type')] = _compactIri( - activeCtx, value['@type'], null, {vocab: true}); - } else if('@language' in value) { - // alias @language - rval[_compactIri(activeCtx, '@language')] = value['@language']; - } - - // alias @value - rval[_compactIri(activeCtx, '@value')] = value['@value']; - - return rval; - } - - // value is a subject reference - var expandedProperty = _expandIri(activeCtx, activeProperty, {vocab: true}); - var type = jsonld.getContextValue(activeCtx, activeProperty, '@type'); - var compacted = _compactIri( - activeCtx, value['@id'], null, {vocab: type === '@vocab'}); - - // compact to scalar - if(type === '@id' || type === '@vocab' || expandedProperty === '@graph') { - return compacted; - } - - var rval = {}; - rval[_compactIri(activeCtx, '@id')] = compacted; - return rval; -} - -/** - * Creates a term definition during context processing. - * - * @param activeCtx the current active context. - * @param localCtx the local context being processed. - * @param term the term in the local context to define the mapping for. - * @param defined a map of defining/defined keys to detect cycles and prevent - * double definitions. - */ -function _createTermDefinition(activeCtx, localCtx, term, defined) { - if(term in defined) { - // term already defined - if(defined[term]) { - return; - } - // cycle detected - throw new JsonLdError( - 'Cyclical context definition detected.', - 'jsonld.CyclicalContext', - {code: 'cyclic IRI mapping', context: localCtx, term: term}); - } - - // now defining term - defined[term] = false; - - if(_isKeyword(term)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; keywords cannot be overridden.', - 'jsonld.SyntaxError', - {code: 'keyword redefinition', context: localCtx, term: term}); - } - - if(term === '') { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a term cannot be an empty string.', - 'jsonld.SyntaxError', - {code: 'invalid term definition', context: localCtx}); - } - - // remove old mapping - if(activeCtx.mappings[term]) { - delete activeCtx.mappings[term]; - } - - // get context term value - var value = localCtx[term]; - - // clear context entry - if(value === null || (_isObject(value) && value['@id'] === null)) { - activeCtx.mappings[term] = null; - defined[term] = true; - return; - } - - // convert short-hand value to object w/@id - if(_isString(value)) { - value = {'@id': value}; - } - - if(!_isObject(value)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context property values must be ' + - 'strings or objects.', - 'jsonld.SyntaxError', - {code: 'invalid term definition', context: localCtx}); - } - - // create new mapping - var mapping = activeCtx.mappings[term] = {}; - mapping.reverse = false; - - if('@reverse' in value) { - if('@id' in value) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a @reverse term definition must not ' + - 'contain @id.', 'jsonld.SyntaxError', - {code: 'invalid reverse property', context: localCtx}); - } - var reverse = value['@reverse']; - if(!_isString(reverse)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a @context @reverse value must be a string.', - 'jsonld.SyntaxError', {code: 'invalid IRI mapping', context: localCtx}); - } - - // expand and add @id mapping - var id = _expandIri( - activeCtx, reverse, {vocab: true, base: false}, localCtx, defined); - if(!_isAbsoluteIri(id)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a @context @reverse value must be an ' + - 'absolute IRI or a blank node identifier.', - 'jsonld.SyntaxError', {code: 'invalid IRI mapping', context: localCtx}); - } - mapping['@id'] = id; - mapping.reverse = true; - } else if('@id' in value) { - var id = value['@id']; - if(!_isString(id)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a @context @id value must be an array ' + - 'of strings or a string.', - 'jsonld.SyntaxError', {code: 'invalid IRI mapping', context: localCtx}); - } - if(id !== term) { - // expand and add @id mapping - id = _expandIri( - activeCtx, id, {vocab: true, base: false}, localCtx, defined); - if(!_isAbsoluteIri(id) && !_isKeyword(id)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; a @context @id value must be an ' + - 'absolute IRI, a blank node identifier, or a keyword.', - 'jsonld.SyntaxError', - {code: 'invalid IRI mapping', context: localCtx}); - } - mapping['@id'] = id; - } - } - - if(!('@id' in mapping)) { - // see if the term has a prefix - var colon = term.indexOf(':'); - if(colon !== -1) { - var prefix = term.substr(0, colon); - if(prefix in localCtx) { - // define parent prefix - _createTermDefinition(activeCtx, localCtx, prefix, defined); - } - - if(activeCtx.mappings[prefix]) { - // set @id based on prefix parent - var suffix = term.substr(colon + 1); - mapping['@id'] = activeCtx.mappings[prefix]['@id'] + suffix; - } else { - // term is an absolute IRI - mapping['@id'] = term; - } - } else { - // non-IRIs *must* define @ids if @vocab is not available - if(!('@vocab' in activeCtx)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context terms must define an @id.', - 'jsonld.SyntaxError', - {code: 'invalid IRI mapping', context: localCtx, term: term}); - } - // prepend vocab to term - mapping['@id'] = activeCtx['@vocab'] + term; - } - } - - // IRI mapping now defined - defined[term] = true; - - if('@type' in value) { - var type = value['@type']; - if(!_isString(type)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an @context @type values must be a string.', - 'jsonld.SyntaxError', - {code: 'invalid type mapping', context: localCtx}); - } - - if(type !== '@id' && type !== '@vocab') { - // expand @type to full IRI - type = _expandIri( - activeCtx, type, {vocab: true, base: false}, localCtx, defined); - if(!_isAbsoluteIri(type)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an @context @type value must be an ' + - 'absolute IRI.', - 'jsonld.SyntaxError', - {code: 'invalid type mapping', context: localCtx}); - } - if(type.indexOf('_:') === 0) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; an @context @type values must be an IRI, ' + - 'not a blank node identifier.', - 'jsonld.SyntaxError', - {code: 'invalid type mapping', context: localCtx}); - } - } - - // add @type to mapping - mapping['@type'] = type; - } - - if('@container' in value) { - var container = value['@container']; - if(container !== '@list' && container !== '@set' && - container !== '@index' && container !== '@language') { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context @container value must be ' + - 'one of the following: @list, @set, @index, or @language.', - 'jsonld.SyntaxError', - {code: 'invalid container mapping', context: localCtx}); - } - if(mapping.reverse && container !== '@index' && container !== '@set' && - container !== null) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context @container value for a @reverse ' + - 'type definition must be @index or @set.', 'jsonld.SyntaxError', - {code: 'invalid reverse property', context: localCtx}); - } - - // add @container to mapping - mapping['@container'] = container; - } - - if('@language' in value && !('@type' in value)) { - var language = value['@language']; - if(language !== null && !_isString(language)) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context @language value must be ' + - 'a string or null.', 'jsonld.SyntaxError', - {code: 'invalid language mapping', context: localCtx}); - } - - // add @language to mapping - if(language !== null) { - language = language.toLowerCase(); - } - mapping['@language'] = language; - } - - // disallow aliasing @context and @preserve - var id = mapping['@id']; - if(id === '@context' || id === '@preserve') { - throw new JsonLdError( - 'Invalid JSON-LD syntax; @context and @preserve cannot be aliased.', - 'jsonld.SyntaxError', {code: 'invalid keyword alias', context: localCtx}); - } -} - -/** - * Expands a string to a full IRI. The string may be a term, a prefix, a - * relative IRI, or an absolute IRI. The associated absolute IRI will be - * returned. - * - * @param activeCtx the current active context. - * @param value the string to expand. - * @param relativeTo options for how to resolve relative IRIs: - * base: true to resolve against the base IRI, false not to. - * vocab: true to concatenate after @vocab, false not to. - * @param localCtx the local context being processed (only given if called - * during context processing). - * @param defined a map for tracking cycles in context definitions (only given - * if called during context processing). - * - * @return the expanded value. - */ -function _expandIri(activeCtx, value, relativeTo, localCtx, defined) { - // already expanded - if(value === null || _isKeyword(value)) { - return value; - } - - // define term dependency if not defined - if(localCtx && value in localCtx && defined[value] !== true) { - _createTermDefinition(activeCtx, localCtx, value, defined); - } - - relativeTo = relativeTo || {}; - if(relativeTo.vocab) { - var mapping = activeCtx.mappings[value]; - - // value is explicitly ignored with a null mapping - if(mapping === null) { - return null; - } - - if(mapping) { - // value is a term - return mapping['@id']; - } - } - - // split value into prefix:suffix - var colon = value.indexOf(':'); - if(colon !== -1) { - var prefix = value.substr(0, colon); - var suffix = value.substr(colon + 1); - - // do not expand blank nodes (prefix of '_') or already-absolute - // IRIs (suffix of '//') - if(prefix === '_' || suffix.indexOf('//') === 0) { - return value; - } - - // prefix dependency not defined, define it - if(localCtx && prefix in localCtx) { - _createTermDefinition(activeCtx, localCtx, prefix, defined); - } - - // use mapping if prefix is defined - var mapping = activeCtx.mappings[prefix]; - if(mapping) { - return mapping['@id'] + suffix; - } - - // already absolute IRI - return value; - } - - // prepend vocab - if(relativeTo.vocab && '@vocab' in activeCtx) { - return activeCtx['@vocab'] + value; - } - - // prepend base - var rval = value; - if(relativeTo.base) { - rval = _prependBase(activeCtx['@base'], rval); - } - - return rval; -} - -/** - * Prepends a base IRI to the given relative IRI. - * - * @param base the base IRI. - * @param iri the relative IRI. - * - * @return the absolute IRI. - */ -function _prependBase(base, iri) { - // skip IRI processing - if(base === null) { - return iri; - } - // already an absolute IRI - if(iri.indexOf(':') !== -1) { - return iri; - } - - // parse base if it is a string - if(_isString(base)) { - base = jsonld.url.parse(base || ''); - } - - // parse given IRI - var rel = jsonld.url.parse(iri); - - // per RFC3986 5.2.2 - var transform = { - protocol: base.protocol || '' - }; - - if(rel.authority !== null) { - transform.authority = rel.authority; - transform.path = rel.path; - transform.query = rel.query; - } else { - transform.authority = base.authority; - - if(rel.path === '') { - transform.path = base.path; - if(rel.query !== null) { - transform.query = rel.query; - } else { - transform.query = base.query; - } - } else { - if(rel.path.indexOf('/') === 0) { - // IRI represents an absolute path - transform.path = rel.path; - } else { - // merge paths - var path = base.path; - - // append relative path to the end of the last directory from base - if(rel.path !== '') { - path = path.substr(0, path.lastIndexOf('/') + 1); - if(path.length > 0 && path.substr(-1) !== '/') { - path += '/'; - } - path += rel.path; - } - - transform.path = path; - } - transform.query = rel.query; - } - } - - // remove slashes and dots in path - transform.path = _removeDotSegments(transform.path, !!transform.authority); - - // construct URL - var rval = transform.protocol; - if(transform.authority !== null) { - rval += '//' + transform.authority; - } - rval += transform.path; - if(transform.query !== null) { - rval += '?' + transform.query; - } - if(rel.fragment !== null) { - rval += '#' + rel.fragment; - } - - // handle empty base - if(rval === '') { - rval = './'; - } - - return rval; -} - -/** - * Removes a base IRI from the given absolute IRI. - * - * @param base the base IRI. - * @param iri the absolute IRI. - * - * @return the relative IRI if relative to base, otherwise the absolute IRI. - */ -function _removeBase(base, iri) { - // skip IRI processing - if(base === null) { - return iri; - } - - if(_isString(base)) { - base = jsonld.url.parse(base || ''); - } - - // establish base root - var root = ''; - if(base.href !== '') { - root += (base.protocol || '') + '//' + (base.authority || ''); - } else if(iri.indexOf('//')) { - // support network-path reference with empty base - root += '//'; - } - - // IRI not relative to base - if(iri.indexOf(root) !== 0) { - return iri; - } - - // remove root from IRI and parse remainder - var rel = jsonld.url.parse(iri.substr(root.length)); - - // remove path segments that match (do not remove last segment unless there - // is a hash or query) - var baseSegments = base.normalizedPath.split('/'); - var iriSegments = rel.normalizedPath.split('/'); - var last = (rel.fragment || rel.query) ? 0 : 1; - while(baseSegments.length > 0 && iriSegments.length > last) { - if(baseSegments[0] !== iriSegments[0]) { - break; - } - baseSegments.shift(); - iriSegments.shift(); - } - - // use '../' for each non-matching base segment - var rval = ''; - if(baseSegments.length > 0) { - // don't count the last segment (if it ends with '/' last path doesn't - // count and if it doesn't end with '/' it isn't a path) - baseSegments.pop(); - for(var i = 0; i < baseSegments.length; ++i) { - rval += '../'; - } - } - - // prepend remaining segments - rval += iriSegments.join('/'); - - // add query and hash - if(rel.query !== null) { - rval += '?' + rel.query; - } - if(rel.fragment !== null) { - rval += '#' + rel.fragment; - } - - // handle empty base - if(rval === '') { - rval = './'; - } - - return rval; -} - -/** - * Gets the initial context. - * - * @param options the options to use: - * [base] the document base IRI. - * - * @return the initial context. - */ -function _getInitialContext(options) { - var base = jsonld.url.parse(options.base || ''); - return { - '@base': base, - mappings: {}, - inverse: null, - getInverse: _createInverseContext, - clone: _cloneActiveContext - }; - - /** - * Generates an inverse context for use in the compaction algorithm, if - * not already generated for the given active context. - * - * @return the inverse context. - */ - function _createInverseContext() { - var activeCtx = this; - - // lazily create inverse - if(activeCtx.inverse) { - return activeCtx.inverse; - } - var inverse = activeCtx.inverse = {}; - - // handle default language - var defaultLanguage = activeCtx['@language'] || '@none'; - - // create term selections for each mapping in the context, ordered by - // shortest and then lexicographically least - var mappings = activeCtx.mappings; - var terms = Object.keys(mappings).sort(_compareShortestLeast); - for(var i = 0; i < terms.length; ++i) { - var term = terms[i]; - var mapping = mappings[term]; - if(mapping === null) { - continue; - } - - var container = mapping['@container'] || '@none'; - - // iterate over every IRI in the mapping - var ids = mapping['@id']; - if(!_isArray(ids)) { - ids = [ids]; - } - for(var ii = 0; ii < ids.length; ++ii) { - var iri = ids[ii]; - var entry = inverse[iri]; - - // initialize entry - if(!entry) { - inverse[iri] = entry = {}; - } - - // add new entry - if(!entry[container]) { - entry[container] = { - '@language': {}, - '@type': {} - }; - } - entry = entry[container]; - - if(mapping.reverse) { - // term is preferred for values using @reverse - _addPreferredTerm(mapping, term, entry['@type'], '@reverse'); - } else if('@type' in mapping) { - // term is preferred for values using specific type - _addPreferredTerm(mapping, term, entry['@type'], mapping['@type']); - } else if('@language' in mapping) { - // term is preferred for values using specific language - var language = mapping['@language'] || '@null'; - _addPreferredTerm(mapping, term, entry['@language'], language); - } else { - // term is preferred for values w/default language or no type and - // no language - // add an entry for the default language - _addPreferredTerm(mapping, term, entry['@language'], defaultLanguage); - - // add entries for no type and no language - _addPreferredTerm(mapping, term, entry['@type'], '@none'); - _addPreferredTerm(mapping, term, entry['@language'], '@none'); - } - } - } - - return inverse; - } - - /** - * Adds the term for the given entry if not already added. - * - * @param mapping the term mapping. - * @param term the term to add. - * @param entry the inverse context typeOrLanguage entry to add to. - * @param typeOrLanguageValue the key in the entry to add to. - */ - function _addPreferredTerm(mapping, term, entry, typeOrLanguageValue) { - if(!(typeOrLanguageValue in entry)) { - entry[typeOrLanguageValue] = term; - } - } - - /** - * Clones an active context, creating a child active context. - * - * @return a clone (child) of the active context. - */ - function _cloneActiveContext() { - var child = {}; - child['@base'] = this['@base']; - child.mappings = _clone(this.mappings); - child.clone = this.clone; - child.inverse = null; - child.getInverse = this.getInverse; - if('@language' in this) { - child['@language'] = this['@language']; - } - if('@vocab' in this) { - child['@vocab'] = this['@vocab']; - } - return child; - } -} - -/** - * Returns whether or not the given value is a keyword. - * - * @param v the value to check. - * - * @return true if the value is a keyword, false if not. - */ -function _isKeyword(v) { - if(!_isString(v)) { - return false; - } - switch(v) { - case '@base': - case '@context': - case '@container': - case '@default': - case '@embed': - case '@explicit': - case '@graph': - case '@id': - case '@index': - case '@language': - case '@list': - case '@omitDefault': - case '@preserve': - case '@requireAll': - case '@reverse': - case '@set': - case '@type': - case '@value': - case '@vocab': - return true; - } - return false; -} - -/** - * Returns true if the given value is an Object. - * - * @param v the value to check. - * - * @return true if the value is an Object, false if not. - */ -function _isObject(v) { - return (Object.prototype.toString.call(v) === '[object Object]'); -} - -/** - * Returns true if the given value is an empty Object. - * - * @param v the value to check. - * - * @return true if the value is an empty Object, false if not. - */ -function _isEmptyObject(v) { - return _isObject(v) && Object.keys(v).length === 0; -} - -/** - * Returns true if the given value is an Array. - * - * @param v the value to check. - * - * @return true if the value is an Array, false if not. - */ -function _isArray(v) { - return Array.isArray(v); -} - -/** - * Throws an exception if the given value is not a valid @type value. - * - * @param v the value to check. - */ -function _validateTypeValue(v) { - // can be a string or an empty object - if(_isString(v) || _isEmptyObject(v)) { - return; - } - - // must be an array - var isValid = false; - if(_isArray(v)) { - // must contain only strings - isValid = true; - for(var i = 0; i < v.length; ++i) { - if(!(_isString(v[i]))) { - isValid = false; - break; - } - } - } - - if(!isValid) { - throw new JsonLdError( - 'Invalid JSON-LD syntax; "@type" value must a string, an array of ' + - 'strings, or an empty object.', 'jsonld.SyntaxError', - {code: 'invalid type value', value: v}); - } -} - -/** - * Returns true if the given value is a String. - * - * @param v the value to check. - * - * @return true if the value is a String, false if not. - */ -function _isString(v) { - return (typeof v === 'string' || - Object.prototype.toString.call(v) === '[object String]'); -} - -/** - * Returns true if the given value is a Number. - * - * @param v the value to check. - * - * @return true if the value is a Number, false if not. - */ -function _isNumber(v) { - return (typeof v === 'number' || - Object.prototype.toString.call(v) === '[object Number]'); -} - -/** - * Returns true if the given value is a double. - * - * @param v the value to check. - * - * @return true if the value is a double, false if not. - */ -function _isDouble(v) { - return _isNumber(v) && String(v).indexOf('.') !== -1; -} - -/** - * Returns true if the given value is numeric. - * - * @param v the value to check. - * - * @return true if the value is numeric, false if not. - */ -function _isNumeric(v) { - return !isNaN(parseFloat(v)) && isFinite(v); -} - -/** - * Returns true if the given value is a Boolean. - * - * @param v the value to check. - * - * @return true if the value is a Boolean, false if not. - */ -function _isBoolean(v) { - return (typeof v === 'boolean' || - Object.prototype.toString.call(v) === '[object Boolean]'); -} - -/** - * Returns true if the given value is undefined. - * - * @param v the value to check. - * - * @return true if the value is undefined, false if not. - */ -function _isUndefined(v) { - return (typeof v === 'undefined'); -} - -/** - * Returns true if the given value is a subject with properties. - * - * @param v the value to check. - * - * @return true if the value is a subject with properties, false if not. - */ -function _isSubject(v) { - // Note: A value is a subject if all of these hold true: - // 1. It is an Object. - // 2. It is not a @value, @set, or @list. - // 3. It has more than 1 key OR any existing key is not @id. - var rval = false; - if(_isObject(v) && - !(('@value' in v) || ('@set' in v) || ('@list' in v))) { - var keyCount = Object.keys(v).length; - rval = (keyCount > 1 || !('@id' in v)); - } - return rval; -} - -/** - * Returns true if the given value is a subject reference. - * - * @param v the value to check. - * - * @return true if the value is a subject reference, false if not. - */ -function _isSubjectReference(v) { - // Note: A value is a subject reference if all of these hold true: - // 1. It is an Object. - // 2. It has a single key: @id. - return (_isObject(v) && Object.keys(v).length === 1 && ('@id' in v)); -} - -/** - * Returns true if the given value is a @value. - * - * @param v the value to check. - * - * @return true if the value is a @value, false if not. - */ -function _isValue(v) { - // Note: A value is a @value if all of these hold true: - // 1. It is an Object. - // 2. It has the @value property. - return _isObject(v) && ('@value' in v); -} - -/** - * Returns true if the given value is a @list. - * - * @param v the value to check. - * - * @return true if the value is a @list, false if not. - */ -function _isList(v) { - // Note: A value is a @list if all of these hold true: - // 1. It is an Object. - // 2. It has the @list property. - return _isObject(v) && ('@list' in v); -} - -/** - * Returns true if the given value is a blank node. - * - * @param v the value to check. - * - * @return true if the value is a blank node, false if not. - */ -function _isBlankNode(v) { - // Note: A value is a blank node if all of these hold true: - // 1. It is an Object. - // 2. If it has an @id key its value begins with '_:'. - // 3. It has no keys OR is not a @value, @set, or @list. - var rval = false; - if(_isObject(v)) { - if('@id' in v) { - rval = (v['@id'].indexOf('_:') === 0); - } else { - rval = (Object.keys(v).length === 0 || - !(('@value' in v) || ('@set' in v) || ('@list' in v))); - } - } - return rval; -} - -/** - * Returns true if the given value is an absolute IRI, false if not. - * - * @param v the value to check. - * - * @return true if the value is an absolute IRI, false if not. - */ -function _isAbsoluteIri(v) { - return _isString(v) && v.indexOf(':') !== -1; -} - -/** - * Clones an object, array, or string/number. If a typed JavaScript object - * is given, such as a Date, it will be converted to a string. - * - * @param value the value to clone. - * - * @return the cloned value. - */ -function _clone(value) { - if(value && typeof value === 'object') { - var rval; - if(_isArray(value)) { - rval = []; - for(var i = 0; i < value.length; ++i) { - rval[i] = _clone(value[i]); - } - } else if(_isObject(value)) { - rval = {}; - for(var key in value) { - rval[key] = _clone(value[key]); - } - } else { - rval = value.toString(); - } - return rval; - } - return value; -} - -/** - * Finds all @context URLs in the given JSON-LD input. - * - * @param input the JSON-LD input. - * @param urls a map of URLs (url => false/@contexts). - * @param replace true to replace the URLs in the given input with the - * @contexts from the urls map, false not to. - * @param base the base IRI to use to resolve relative IRIs. - * - * @return true if new URLs to retrieve were found, false if not. - */ -function _findContextUrls(input, urls, replace, base) { - var count = Object.keys(urls).length; - if(_isArray(input)) { - for(var i = 0; i < input.length; ++i) { - _findContextUrls(input[i], urls, replace, base); - } - return (count < Object.keys(urls).length); - } else if(_isObject(input)) { - for(var key in input) { - if(key !== '@context') { - _findContextUrls(input[key], urls, replace, base); - continue; - } - - // get @context - var ctx = input[key]; - - // array @context - if(_isArray(ctx)) { - var length = ctx.length; - for(var i = 0; i < length; ++i) { - var _ctx = ctx[i]; - if(_isString(_ctx)) { - _ctx = _prependBase(base, _ctx); - // replace w/@context if requested - if(replace) { - _ctx = urls[_ctx]; - if(_isArray(_ctx)) { - // add flattened context - Array.prototype.splice.apply(ctx, [i, 1].concat(_ctx)); - i += _ctx.length - 1; - length = ctx.length; - } else { - ctx[i] = _ctx; - } - } else if(!(_ctx in urls)) { - // @context URL found - urls[_ctx] = false; - } - } - } - } else if(_isString(ctx)) { - // string @context - ctx = _prependBase(base, ctx); - // replace w/@context if requested - if(replace) { - input[key] = urls[ctx]; - } else if(!(ctx in urls)) { - // @context URL found - urls[ctx] = false; - } - } - } - return (count < Object.keys(urls).length); - } - return false; -} - -/** - * Retrieves external @context URLs using the given document loader. Every - * instance of @context in the input that refers to a URL will be replaced - * with the JSON @context found at that URL. - * - * @param input the JSON-LD input with possible contexts. - * @param options the options to use: - * documentLoader(url, callback(err, remoteDoc)) the document loader. - * @param callback(err, input) called once the operation completes. - */ -function _retrieveContextUrls(input, options, callback) { - // if any error occurs during URL resolution, quit - var error = null; - - // recursive document loader - var documentLoader = options.documentLoader; - var retrieve = function(input, cycles, documentLoader, base, callback) { - if(Object.keys(cycles).length > MAX_CONTEXT_URLS) { - error = new JsonLdError( - 'Maximum number of @context URLs exceeded.', - 'jsonld.ContextUrlError', - {code: 'loading remote context failed', max: MAX_CONTEXT_URLS}); - return callback(error); - } - - // for tracking the URLs to retrieve - var urls = {}; - - // finished will be called once the URL queue is empty - var finished = function() { - // replace all URLs in the input - _findContextUrls(input, urls, true, base); - callback(null, input); - }; - - // find all URLs in the given input - if(!_findContextUrls(input, urls, false, base)) { - // no new URLs in input - finished(); - } - - // queue all unretrieved URLs - var queue = []; - for(var url in urls) { - if(urls[url] === false) { - queue.push(url); - } - } - - // retrieve URLs in queue - var count = queue.length; - for(var i = 0; i < queue.length; ++i) { - (function(url) { - // check for context URL cycle - if(url in cycles) { - error = new JsonLdError( - 'Cyclical @context URLs detected.', - 'jsonld.ContextUrlError', - {code: 'recursive context inclusion', url: url}); - return callback(error); - } - var _cycles = _clone(cycles); - _cycles[url] = true; - var done = function(err, remoteDoc) { - // short-circuit if there was an error with another URL - if(error) { - return; - } - - var ctx = remoteDoc ? remoteDoc.document : null; - - // parse string context as JSON - if(!err && _isString(ctx)) { - try { - ctx = JSON.parse(ctx); - } catch(ex) { - err = ex; - } - } - - // ensure ctx is an object - if(err) { - err = new JsonLdError( - 'Dereferencing a URL did not result in a valid JSON-LD object. ' + - 'Possible causes are an inaccessible URL perhaps due to ' + - 'a same-origin policy (ensure the server uses CORS if you are ' + - 'using client-side JavaScript), too many redirects, a ' + - 'non-JSON response, or more than one HTTP Link Header was ' + - 'provided for a remote context.', - 'jsonld.InvalidUrl', - {code: 'loading remote context failed', url: url, cause: err}); - } else if(!_isObject(ctx)) { - err = new JsonLdError( - 'Dereferencing a URL did not result in a JSON object. The ' + - 'response was valid JSON, but it was not a JSON object.', - 'jsonld.InvalidUrl', - {code: 'invalid remote context', url: url, cause: err}); - } - if(err) { - error = err; - return callback(error); - } - - // use empty context if no @context key is present - if(!('@context' in ctx)) { - ctx = {'@context': {}}; - } else { - ctx = {'@context': ctx['@context']}; - } - - // append context URL to context if given - if(remoteDoc.contextUrl) { - if(!_isArray(ctx['@context'])) { - ctx['@context'] = [ctx['@context']]; - } - ctx['@context'].push(remoteDoc.contextUrl); - } - - // recurse - retrieve(ctx, _cycles, documentLoader, url, function(err, ctx) { - if(err) { - return callback(err); - } - urls[url] = ctx['@context']; - count -= 1; - if(count === 0) { - finished(); - } - }); - }; - var promise = documentLoader(url, done); - if(promise && 'then' in promise) { - promise.then(done.bind(null, null), done); - } - }(queue[i])); - } - }; - retrieve(input, {}, documentLoader, options.base, callback); -} - -// define js 1.8.5 Object.keys method if not present -if(!Object.keys) { - Object.keys = function(o) { - if(o !== Object(o)) { - throw new TypeError('Object.keys called on non-object'); - } - var rval = []; - for(var p in o) { - if(Object.prototype.hasOwnProperty.call(o, p)) { - rval.push(p); - } - } - return rval; - }; -} - -/** - * Parses RDF in the form of N-Quads. - * - * @param input the N-Quads input to parse. - * - * @return an RDF dataset. - */ -function _parseNQuads(input) { - // define partial regexes - var iri = '(?:<([^:]+:[^>]*)>)'; - var bnode = '(_:(?:[A-Za-z0-9]+))'; - var plain = '"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"'; - var datatype = '(?:\\^\\^' + iri + ')'; - var language = '(?:@([a-z]+(?:-[a-z0-9]+)*))'; - var literal = '(?:' + plain + '(?:' + datatype + '|' + language + ')?)'; - var ws = '[ \\t]+'; - var wso = '[ \\t]*'; - var eoln = /(?:\r\n)|(?:\n)|(?:\r)/g; - var empty = new RegExp('^' + wso + '$'); - - // define quad part regexes - var subject = '(?:' + iri + '|' + bnode + ')' + ws; - var property = iri + ws; - var object = '(?:' + iri + '|' + bnode + '|' + literal + ')' + wso; - var graphName = '(?:\\.|(?:(?:' + iri + '|' + bnode + ')' + wso + '\\.))'; - - // full quad regex - var quad = new RegExp( - '^' + wso + subject + property + object + graphName + wso + '$'); - - // build RDF dataset - var dataset = {}; - - // split N-Quad input into lines - var lines = input.split(eoln); - var lineNumber = 0; - for(var li = 0; li < lines.length; ++li) { - var line = lines[li]; - lineNumber++; - - // skip empty lines - if(empty.test(line)) { - continue; - } - - // parse quad - var match = line.match(quad); - if(match === null) { - throw new JsonLdError( - 'Error while parsing N-Quads; invalid quad.', - 'jsonld.ParseError', {line: lineNumber}); - } - - // create RDF triple - var triple = {}; - - // get subject - if(!_isUndefined(match[1])) { - triple.subject = {type: 'IRI', value: match[1]}; - } else { - triple.subject = {type: 'blank node', value: match[2]}; - } - - // get predicate - triple.predicate = {type: 'IRI', value: match[3]}; - - // get object - if(!_isUndefined(match[4])) { - triple.object = {type: 'IRI', value: match[4]}; - } else if(!_isUndefined(match[5])) { - triple.object = {type: 'blank node', value: match[5]}; - } else { - triple.object = {type: 'literal'}; - if(!_isUndefined(match[7])) { - triple.object.datatype = match[7]; - } else if(!_isUndefined(match[8])) { - triple.object.datatype = RDF_LANGSTRING; - triple.object.language = match[8]; - } else { - triple.object.datatype = XSD_STRING; - } - var unescaped = match[6] - .replace(/\\"/g, '"') - .replace(/\\t/g, '\t') - .replace(/\\n/g, '\n') - .replace(/\\r/g, '\r') - .replace(/\\\\/g, '\\'); - triple.object.value = unescaped; - } - - // get graph name ('@default' is used for the default graph) - var name = '@default'; - if(!_isUndefined(match[9])) { - name = match[9]; - } else if(!_isUndefined(match[10])) { - name = match[10]; - } - - // initialize graph in dataset - if(!(name in dataset)) { - dataset[name] = [triple]; - } else { - // add triple if unique to its graph - var unique = true; - var triples = dataset[name]; - for(var ti = 0; unique && ti < triples.length; ++ti) { - if(_compareRDFTriples(triples[ti], triple)) { - unique = false; - } - } - if(unique) { - triples.push(triple); - } - } - } - - return dataset; -} - -// register the N-Quads RDF parser -jsonld.registerRDFParser('application/nquads', _parseNQuads); - -/** - * Converts an RDF dataset to N-Quads. - * - * @param dataset the RDF dataset to convert. - * - * @return the N-Quads string. - */ -function _toNQuads(dataset) { - var quads = []; - for(var graphName in dataset) { - var triples = dataset[graphName]; - for(var ti = 0; ti < triples.length; ++ti) { - var triple = triples[ti]; - if(graphName === '@default') { - graphName = null; - } - quads.push(_toNQuad(triple, graphName)); - } - } - quads.sort(); - return quads.join(''); -} - -/** - * Converts an RDF triple and graph name to an N-Quad string (a single quad). - * - * @param triple the RDF triple to convert. - * @param graphName the name of the graph containing the triple, null for - * the default graph. - * @param bnode the bnode the quad is mapped to (optional, for use - * during normalization only). - * - * @return the N-Quad string. - */ -function _toNQuad(triple, graphName, bnode) { - var s = triple.subject; - var p = triple.predicate; - var o = triple.object; - var g = graphName; - - var quad = ''; - - // subject is an IRI - if(s.type === 'IRI') { - quad += '<' + s.value + '>'; - } else if(bnode) { - // bnode normalization mode - quad += (s.value === bnode) ? '_:a' : '_:z'; - } else { - // bnode normal mode - quad += s.value; - } - quad += ' '; - - // predicate is an IRI - if(p.type === 'IRI') { - quad += '<' + p.value + '>'; - } else if(bnode) { - // FIXME: TBD what to do with bnode predicates during normalization - // bnode normalization mode - quad += '_:p'; - } else { - // bnode normal mode - quad += p.value; - } - quad += ' '; - - // object is IRI, bnode, or literal - if(o.type === 'IRI') { - quad += '<' + o.value + '>'; - } else if(o.type === 'blank node') { - // normalization mode - if(bnode) { - quad += (o.value === bnode) ? '_:a' : '_:z'; - } else { - // normal mode - quad += o.value; - } - } else { - var escaped = o.value - .replace(/\\/g, '\\\\') - .replace(/\t/g, '\\t') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') - .replace(/\"/g, '\\"'); - quad += '"' + escaped + '"'; - if(o.datatype === RDF_LANGSTRING) { - if(o.language) { - quad += '@' + o.language; - } - } else if(o.datatype !== XSD_STRING) { - quad += '^^<' + o.datatype + '>'; - } - } - - // graph - if(g !== null) { - if(g.indexOf('_:') !== 0) { - quad += ' <' + g + '>'; - } else if(bnode) { - quad += ' _:g'; - } else { - quad += ' ' + g; - } - } - - quad += ' .\n'; - return quad; -} - -/** - * Parses the RDF dataset found via the data object from the RDFa API. - * - * @param data the RDFa API data object. - * - * @return the RDF dataset. - */ -function _parseRdfaApiData(data) { - var dataset = {}; - dataset['@default'] = []; - - var subjects = data.getSubjects(); - for(var si = 0; si < subjects.length; ++si) { - var subject = subjects[si]; - if(subject === null) { - continue; - } - - // get all related triples - var triples = data.getSubjectTriples(subject); - if(triples === null) { - continue; - } - var predicates = triples.predicates; - for(var predicate in predicates) { - // iterate over objects - var objects = predicates[predicate].objects; - for(var oi = 0; oi < objects.length; ++oi) { - var object = objects[oi]; - - // create RDF triple - var triple = {}; - - // add subject - if(subject.indexOf('_:') === 0) { - triple.subject = {type: 'blank node', value: subject}; - } else { - triple.subject = {type: 'IRI', value: subject}; - } - - // add predicate - if(predicate.indexOf('_:') === 0) { - triple.predicate = {type: 'blank node', value: predicate}; - } else { - triple.predicate = {type: 'IRI', value: predicate}; - } - - // serialize XML literal - var value = object.value; - if(object.type === RDF_XML_LITERAL) { - // initialize XMLSerializer - if(!XMLSerializer) { - _defineXMLSerializer(); - } - var serializer = new XMLSerializer(); - value = ''; - for(var x = 0; x < object.value.length; x++) { - if(object.value[x].nodeType === Node.ELEMENT_NODE) { - value += serializer.serializeToString(object.value[x]); - } else if(object.value[x].nodeType === Node.TEXT_NODE) { - value += object.value[x].nodeValue; - } - } - } - - // add object - triple.object = {}; - - // object is an IRI - if(object.type === RDF_OBJECT) { - if(object.value.indexOf('_:') === 0) { - triple.object.type = 'blank node'; - } else { - triple.object.type = 'IRI'; - } - } else { - // object is a literal - triple.object.type = 'literal'; - if(object.type === RDF_PLAIN_LITERAL) { - if(object.language) { - triple.object.datatype = RDF_LANGSTRING; - triple.object.language = object.language; - } else { - triple.object.datatype = XSD_STRING; - } - } else { - triple.object.datatype = object.type; - } - } - triple.object.value = value; - - // add triple to dataset in default graph - dataset['@default'].push(triple); - } - } - } - - return dataset; -} - -// register the RDFa API RDF parser -jsonld.registerRDFParser('rdfa-api', _parseRdfaApiData); - -/** - * Creates a new UniqueNamer. A UniqueNamer issues unique names, keeping - * track of any previously issued names. - * - * @param prefix the prefix to use (''). - */ -function UniqueNamer(prefix) { - this.prefix = prefix; - this.counter = 0; - this.existing = {}; -} -jsonld.UniqueNamer = UniqueNamer; - -/** - * Copies this UniqueNamer. - * - * @return a copy of this UniqueNamer. - */ -UniqueNamer.prototype.clone = function() { - var copy = new UniqueNamer(this.prefix); - copy.counter = this.counter; - copy.existing = _clone(this.existing); - return copy; -}; - -/** - * Gets the new name for the given old name, where if no old name is given - * a new name will be generated. - * - * @param [oldName] the old name to get the new name for. - * - * @return the new name. - */ -UniqueNamer.prototype.getName = function(oldName) { - // return existing old name - if(oldName && oldName in this.existing) { - return this.existing[oldName]; - } - - // get next name - var name = this.prefix + this.counter; - this.counter += 1; - - // save mapping - if(oldName) { - this.existing[oldName] = name; - } - - return name; -}; - -/** - * Returns true if the given oldName has already been assigned a new name. - * - * @param oldName the oldName to check. - * - * @return true if the oldName has been assigned a new name, false if not. - */ -UniqueNamer.prototype.isNamed = function(oldName) { - return (oldName in this.existing); -}; - -/** - * A Permutator iterates over all possible permutations of the given array - * of elements. - * - * @param list the array of elements to iterate over. - */ -var Permutator = function(list) { - // original array - this.list = list.sort(); - // indicates whether there are more permutations - this.done = false; - // directional info for permutation algorithm - this.left = {}; - for(var i = 0; i < list.length; ++i) { - this.left[list[i]] = true; - } -}; - -/** - * Returns true if there is another permutation. - * - * @return true if there is another permutation, false if not. - */ -Permutator.prototype.hasNext = function() { - return !this.done; -}; - -/** - * Gets the next permutation. Call hasNext() to ensure there is another one - * first. - * - * @return the next permutation. - */ -Permutator.prototype.next = function() { - // copy current permutation - var rval = this.list.slice(); - - /* Calculate the next permutation using the Steinhaus-Johnson-Trotter - permutation algorithm. */ - - // get largest mobile element k - // (mobile: element is greater than the one it is looking at) - var k = null; - var pos = 0; - var length = this.list.length; - for(var i = 0; i < length; ++i) { - var element = this.list[i]; - var left = this.left[element]; - if((k === null || element > k) && - ((left && i > 0 && element > this.list[i - 1]) || - (!left && i < (length - 1) && element > this.list[i + 1]))) { - k = element; - pos = i; - } - } - - // no more permutations - if(k === null) { - this.done = true; - } else { - // swap k and the element it is looking at - var swap = this.left[k] ? pos - 1 : pos + 1; - this.list[pos] = this.list[swap]; - this.list[swap] = k; - - // reverse the direction of all elements larger than k - for(var i = 0; i < length; ++i) { - if(this.list[i] > k) { - this.left[this.list[i]] = !this.left[this.list[i]]; - } - } - } - - return rval; -}; - -// SHA-1 API -var sha1 = jsonld.sha1 = {}; - -if(_nodejs) { - var crypto = require('crypto'); - sha1.create = function() { - var md = crypto.createHash('sha1'); - return { - update: function(data) { - md.update(data, 'utf8'); - }, - digest: function() { - return md.digest('hex'); - } - }; - }; -} else { - sha1.create = function() { - return new sha1.MessageDigest(); - }; -} - -/** - * Hashes the given array of quads and returns its hexadecimal SHA-1 message - * digest. - * - * @param nquads the list of serialized quads to hash. - * - * @return the hexadecimal SHA-1 message digest. - */ -sha1.hash = function(nquads) { - var md = sha1.create(); - for(var i = 0; i < nquads.length; ++i) { - md.update(nquads[i]); - } - return md.digest(); -}; - -// only define sha1 MessageDigest for non-nodejs -if(!_nodejs) { - -/** - * Creates a simple byte buffer for message digest operations. - */ -sha1.Buffer = function() { - this.data = ''; - this.read = 0; -}; - -/** - * Puts a 32-bit integer into this buffer in big-endian order. - * - * @param i the 32-bit integer. - */ -sha1.Buffer.prototype.putInt32 = function(i) { - this.data += ( - String.fromCharCode(i >> 24 & 0xFF) + - String.fromCharCode(i >> 16 & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i & 0xFF)); -}; - -/** - * Gets a 32-bit integer from this buffer in big-endian order and - * advances the read pointer by 4. - * - * @return the word. - */ -sha1.Buffer.prototype.getInt32 = function() { - var rval = ( - this.data.charCodeAt(this.read) << 24 ^ - this.data.charCodeAt(this.read + 1) << 16 ^ - this.data.charCodeAt(this.read + 2) << 8 ^ - this.data.charCodeAt(this.read + 3)); - this.read += 4; - return rval; -}; - -/** - * Gets the bytes in this buffer. - * - * @return a string full of UTF-8 encoded characters. - */ -sha1.Buffer.prototype.bytes = function() { - return this.data.slice(this.read); -}; - -/** - * Gets the number of bytes in this buffer. - * - * @return the number of bytes in this buffer. - */ -sha1.Buffer.prototype.length = function() { - return this.data.length - this.read; -}; - -/** - * Compacts this buffer. - */ -sha1.Buffer.prototype.compact = function() { - this.data = this.data.slice(this.read); - this.read = 0; -}; - -/** - * Converts this buffer to a hexadecimal string. - * - * @return a hexadecimal string. - */ -sha1.Buffer.prototype.toHex = function() { - var rval = ''; - for(var i = this.read; i < this.data.length; ++i) { - var b = this.data.charCodeAt(i); - if(b < 16) { - rval += '0'; - } - rval += b.toString(16); - } - return rval; -}; - -/** - * Creates a SHA-1 message digest object. - * - * @return a message digest object. - */ -sha1.MessageDigest = function() { - // do initialization as necessary - if(!_sha1.initialized) { - _sha1.init(); - } - - this.blockLength = 64; - this.digestLength = 20; - // length of message so far (does not including padding) - this.messageLength = 0; - - // input buffer - this.input = new sha1.Buffer(); - - // for storing words in the SHA-1 algorithm - this.words = new Array(80); - - // SHA-1 state contains five 32-bit integers - this.state = { - h0: 0x67452301, - h1: 0xEFCDAB89, - h2: 0x98BADCFE, - h3: 0x10325476, - h4: 0xC3D2E1F0 - }; -}; - -/** - * Updates the digest with the given string input. - * - * @param msg the message input to update with. - */ -sha1.MessageDigest.prototype.update = function(msg) { - // UTF-8 encode message - msg = unescape(encodeURIComponent(msg)); - - // update message length and input buffer - this.messageLength += msg.length; - this.input.data += msg; - - // process input - _sha1.update(this.state, this.words, this.input); - - // compact input buffer every 2K or if empty - if(this.input.read > 2048 || this.input.length() === 0) { - this.input.compact(); - } -}; - -/** - * Produces the digest. - * - * @return the digest as a hexadecimal string. - */ -sha1.MessageDigest.prototype.digest = function() { - /* Determine the number of bytes that must be added to the message - to ensure its length is congruent to 448 mod 512. In other words, - a 64-bit integer that gives the length of the message will be - appended to the message and whatever the length of the message is - plus 64 bits must be a multiple of 512. So the length of the - message must be congruent to 448 mod 512 because 512 - 64 = 448. - - In order to fill up the message length it must be filled with - padding that begins with 1 bit followed by all 0 bits. Padding - must *always* be present, so if the message length is already - congruent to 448 mod 512, then 512 padding bits must be added. */ - - // 512 bits == 64 bytes, 448 bits == 56 bytes, 64 bits = 8 bytes - // _padding starts with 1 byte with first bit is set in it which - // is byte value 128, then there may be up to 63 other pad bytes - var len = this.messageLength; - var padBytes = new sha1.Buffer(); - padBytes.data += this.input.bytes(); - padBytes.data += _sha1.padding.substr(0, 64 - ((len + 8) % 64)); - - /* Now append length of the message. The length is appended in bits - as a 64-bit number in big-endian order. Since we store the length - in bytes, we must multiply it by 8 (or left shift by 3). So here - store the high 3 bits in the low end of the first 32-bits of the - 64-bit number and the lower 5 bits in the high end of the second - 32-bits. */ - padBytes.putInt32((len >>> 29) & 0xFF); - padBytes.putInt32((len << 3) & 0xFFFFFFFF); - _sha1.update(this.state, this.words, padBytes); - var rval = new sha1.Buffer(); - rval.putInt32(this.state.h0); - rval.putInt32(this.state.h1); - rval.putInt32(this.state.h2); - rval.putInt32(this.state.h3); - rval.putInt32(this.state.h4); - return rval.toHex(); -}; - -// private SHA-1 data -var _sha1 = { - padding: null, - initialized: false -}; - -/** - * Initializes the constant tables. - */ -_sha1.init = function() { - // create padding - _sha1.padding = String.fromCharCode(128); - var c = String.fromCharCode(0x00); - var n = 64; - while(n > 0) { - if(n & 1) { - _sha1.padding += c; - } - n >>>= 1; - if(n > 0) { - c += c; - } - } - - // now initialized - _sha1.initialized = true; -}; - -/** - * Updates a SHA-1 state with the given byte buffer. - * - * @param s the SHA-1 state to update. - * @param w the array to use to store words. - * @param input the input byte buffer. - */ -_sha1.update = function(s, w, input) { - // consume 512 bit (64 byte) chunks - var t, a, b, c, d, e, f, i; - var len = input.length(); - while(len >= 64) { - // the w array will be populated with sixteen 32-bit big-endian words - // and then extended into 80 32-bit words according to SHA-1 algorithm - // and for 32-79 using Max Locktyukhin's optimization - - // initialize hash value for this chunk - a = s.h0; - b = s.h1; - c = s.h2; - d = s.h3; - e = s.h4; - - // round 1 - for(i = 0; i < 16; ++i) { - t = input.getInt32(); - w[i] = t; - f = d ^ (b & (c ^ d)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - for(; i < 20; ++i) { - t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); - t = (t << 1) | (t >>> 31); - w[i] = t; - f = d ^ (b & (c ^ d)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - // round 2 - for(; i < 32; ++i) { - t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); - t = (t << 1) | (t >>> 31); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - for(; i < 40; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - // round 3 - for(; i < 60; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = (b & c) | (d & (b ^ c)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x8F1BBCDC + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - // round 4 - for(; i < 80; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0xCA62C1D6 + t; - e = d; - d = c; - c = (b << 30) | (b >>> 2); - b = a; - a = t; - } - - // update hash state - s.h0 += a; - s.h1 += b; - s.h2 += c; - s.h3 += d; - s.h4 += e; - - len -= 64; - } -}; - -} // end non-nodejs - -if(!XMLSerializer) { - -var _defineXMLSerializer = function() { - XMLSerializer = require('xmldom').XMLSerializer; -}; - -} // end _defineXMLSerializer - -// define URL parser -// parseUri 1.2.2 -// (c) Steven Levithan -// MIT License -// with local jsonld.js modifications -jsonld.url = {}; -jsonld.url.parsers = { - simple: { - // RFC 3986 basic parts - keys: ['href','scheme','authority','path','query','fragment'], - regex: /^(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/ - }, - full: { - keys: ['href','protocol','scheme','authority','auth','user','password','hostname','port','path','directory','file','query','fragment'], - regex: /^(([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?(?:(((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/ - } -}; -jsonld.url.parse = function(str, parser) { - var parsed = {}; - var o = jsonld.url.parsers[parser || 'full']; - var m = o.regex.exec(str); - var i = o.keys.length; - while(i--) { - parsed[o.keys[i]] = (m[i] === undefined) ? null : m[i]; - } - parsed.normalizedPath = _removeDotSegments(parsed.path, !!parsed.authority); - return parsed; -}; - -/** - * Removes dot segments from a URL path. - * - * @param path the path to remove dot segments from. - * @param hasAuthority true if the URL has an authority, false if not. - */ -function _removeDotSegments(path, hasAuthority) { - var rval = ''; - - if(path.indexOf('/') === 0) { - rval = '/'; - } - - // RFC 3986 5.2.4 (reworked) - var input = path.split('/'); - var output = []; - while(input.length > 0) { - if(input[0] === '.' || (input[0] === '' && input.length > 1)) { - input.shift(); - continue; - } - if(input[0] === '..') { - input.shift(); - if(hasAuthority || - (output.length > 0 && output[output.length - 1] !== '..')) { - output.pop(); - } else { - // leading relative URL '..' - output.push('..'); - } - continue; - } - output.push(input.shift()); - } - - return rval + output.join('/'); -} - -if(_nodejs) { - // use node document loader by default - jsonld.useDocumentLoader('node'); -} else if(typeof XMLHttpRequest !== 'undefined') { - // use xhr document loader by default - jsonld.useDocumentLoader('xhr'); -} - -if(_nodejs) { - jsonld.use = function(extension) { - switch(extension) { - case 'request': - // use node JSON-LD request extension - jsonld.request = require('./request'); - break; - default: - throw new JsonLdError( - 'Unknown extension.', - 'jsonld.UnknownExtension', {extension: extension}); - } - }; - - // expose version - var _module = {exports: {}, filename: __dirname}; - require('pkginfo')(_module, 'version'); - jsonld.version = _module.exports.version; -} - -// end of jsonld API factory -return jsonld; -}; - -// external APIs: - -// used to generate a new jsonld API instance -var factory = function() { - return wrapper(function() { - return factory(); - }); -}; - -if(!_nodejs && (typeof define === 'function' && define.amd)) { - // export AMD API - define([], function() { - // now that module is defined, wrap main jsonld API instance - wrapper(factory); - return factory; - }); -} else { - // wrap the main jsonld API instance - wrapper(factory); - - if(_nodejs) { - // export nodejs API - module.exports = factory; - } else if(_browser) { - // export simple browser API - if(typeof jsonld === 'undefined') { - jsonld = jsonldjs = factory; - } else { - jsonldjs = factory; - } - } -} - -})(); - -module.exports = jsonldjs; -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},"/node_modules/jsonld/js") -},{"./request":2,"_process":48,"crypto":2,"es6-promise":4,"http":2,"pkginfo":5,"request":2,"util":2,"xmldom":2}],4:[function(require,module,exports){ -(function (process,global){ -/*! - * @overview es6-promise - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE - * @version 2.0.1 - */ - -(function() { - "use strict"; - - function $$utils$$objectOrFunction(x) { - return typeof x === 'function' || (typeof x === 'object' && x !== null); - } - - function $$utils$$isFunction(x) { - return typeof x === 'function'; - } - - function $$utils$$isMaybeThenable(x) { - return typeof x === 'object' && x !== null; - } - - var $$utils$$_isArray; - - if (!Array.isArray) { - $$utils$$_isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; - } else { - $$utils$$_isArray = Array.isArray; - } - - var $$utils$$isArray = $$utils$$_isArray; - var $$utils$$now = Date.now || function() { return new Date().getTime(); }; - function $$utils$$F() { } - - var $$utils$$o_create = (Object.create || function (o) { - if (arguments.length > 1) { - throw new Error('Second argument not supported'); - } - if (typeof o !== 'object') { - throw new TypeError('Argument must be an object'); - } - $$utils$$F.prototype = o; - return new $$utils$$F(); - }); - - var $$asap$$len = 0; - - var $$asap$$default = function asap(callback, arg) { - $$asap$$queue[$$asap$$len] = callback; - $$asap$$queue[$$asap$$len + 1] = arg; - $$asap$$len += 2; - if ($$asap$$len === 2) { - // If len is 1, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - $$asap$$scheduleFlush(); - } - }; - - var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {}; - var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver; - - // test for web worker but not in IE10 - var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && - typeof importScripts !== 'undefined' && - typeof MessageChannel !== 'undefined'; - - // node - function $$asap$$useNextTick() { - return function() { - process.nextTick($$asap$$flush); - }; - } - - function $$asap$$useMutationObserver() { - var iterations = 0; - var observer = new $$asap$$BrowserMutationObserver($$asap$$flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function() { - node.data = (iterations = ++iterations % 2); - }; - } - - // web worker - function $$asap$$useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = $$asap$$flush; - return function () { - channel.port2.postMessage(0); - }; - } - - function $$asap$$useSetTimeout() { - return function() { - setTimeout($$asap$$flush, 1); - }; - } - - var $$asap$$queue = new Array(1000); - - function $$asap$$flush() { - for (var i = 0; i < $$asap$$len; i+=2) { - var callback = $$asap$$queue[i]; - var arg = $$asap$$queue[i+1]; - - callback(arg); - - $$asap$$queue[i] = undefined; - $$asap$$queue[i+1] = undefined; - } - - $$asap$$len = 0; - } - - var $$asap$$scheduleFlush; - - // Decide what async method to use to triggering processing of queued callbacks: - if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { - $$asap$$scheduleFlush = $$asap$$useNextTick(); - } else if ($$asap$$BrowserMutationObserver) { - $$asap$$scheduleFlush = $$asap$$useMutationObserver(); - } else if ($$asap$$isWorker) { - $$asap$$scheduleFlush = $$asap$$useMessageChannel(); - } else { - $$asap$$scheduleFlush = $$asap$$useSetTimeout(); - } - - function $$$internal$$noop() {} - var $$$internal$$PENDING = void 0; - var $$$internal$$FULFILLED = 1; - var $$$internal$$REJECTED = 2; - var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject(); - - function $$$internal$$selfFullfillment() { - return new TypeError("You cannot resolve a promise with itself"); - } - - function $$$internal$$cannotReturnOwn() { - return new TypeError('A promises callback cannot return that same promise.') - } - - function $$$internal$$getThen(promise) { - try { - return promise.then; - } catch(error) { - $$$internal$$GET_THEN_ERROR.error = error; - return $$$internal$$GET_THEN_ERROR; - } - } - - function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch(e) { - return e; - } - } - - function $$$internal$$handleForeignThenable(promise, thenable, then) { - $$asap$$default(function(promise) { - var sealed = false; - var error = $$$internal$$tryThen(then, thenable, function(value) { - if (sealed) { return; } - sealed = true; - if (thenable !== value) { - $$$internal$$resolve(promise, value); - } else { - $$$internal$$fulfill(promise, value); - } - }, function(reason) { - if (sealed) { return; } - sealed = true; - - $$$internal$$reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - $$$internal$$reject(promise, error); - } - }, promise); - } - - function $$$internal$$handleOwnThenable(promise, thenable) { - if (thenable._state === $$$internal$$FULFILLED) { - $$$internal$$fulfill(promise, thenable._result); - } else if (promise._state === $$$internal$$REJECTED) { - $$$internal$$reject(promise, thenable._result); - } else { - $$$internal$$subscribe(thenable, undefined, function(value) { - $$$internal$$resolve(promise, value); - }, function(reason) { - $$$internal$$reject(promise, reason); - }); - } - } - - function $$$internal$$handleMaybeThenable(promise, maybeThenable) { - if (maybeThenable.constructor === promise.constructor) { - $$$internal$$handleOwnThenable(promise, maybeThenable); - } else { - var then = $$$internal$$getThen(maybeThenable); - - if (then === $$$internal$$GET_THEN_ERROR) { - $$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error); - } else if (then === undefined) { - $$$internal$$fulfill(promise, maybeThenable); - } else if ($$utils$$isFunction(then)) { - $$$internal$$handleForeignThenable(promise, maybeThenable, then); - } else { - $$$internal$$fulfill(promise, maybeThenable); - } - } - } - - function $$$internal$$resolve(promise, value) { - if (promise === value) { - $$$internal$$reject(promise, $$$internal$$selfFullfillment()); - } else if ($$utils$$objectOrFunction(value)) { - $$$internal$$handleMaybeThenable(promise, value); - } else { - $$$internal$$fulfill(promise, value); - } - } - - function $$$internal$$publishRejection(promise) { - if (promise._onerror) { - promise._onerror(promise._result); - } - - $$$internal$$publish(promise); - } - - function $$$internal$$fulfill(promise, value) { - if (promise._state !== $$$internal$$PENDING) { return; } - - promise._result = value; - promise._state = $$$internal$$FULFILLED; - - if (promise._subscribers.length === 0) { - } else { - $$asap$$default($$$internal$$publish, promise); - } - } - - function $$$internal$$reject(promise, reason) { - if (promise._state !== $$$internal$$PENDING) { return; } - promise._state = $$$internal$$REJECTED; - promise._result = reason; - - $$asap$$default($$$internal$$publishRejection, promise); - } - - function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) { - var subscribers = parent._subscribers; - var length = subscribers.length; - - parent._onerror = null; - - subscribers[length] = child; - subscribers[length + $$$internal$$FULFILLED] = onFulfillment; - subscribers[length + $$$internal$$REJECTED] = onRejection; - - if (length === 0 && parent._state) { - $$asap$$default($$$internal$$publish, parent); - } - } - - function $$$internal$$publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (subscribers.length === 0) { return; } - - var child, callback, detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - $$$internal$$invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; - } - - function $$$internal$$ErrorObject() { - this.error = null; - } - - var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject(); - - function $$$internal$$tryCatch(callback, detail) { - try { - return callback(detail); - } catch(e) { - $$$internal$$TRY_CATCH_ERROR.error = e; - return $$$internal$$TRY_CATCH_ERROR; - } - } - - function $$$internal$$invokeCallback(settled, promise, callback, detail) { - var hasCallback = $$utils$$isFunction(callback), - value, error, succeeded, failed; - - if (hasCallback) { - value = $$$internal$$tryCatch(callback, detail); - - if (value === $$$internal$$TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; - } - - if (promise === value) { - $$$internal$$reject(promise, $$$internal$$cannotReturnOwn()); - return; - } - - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== $$$internal$$PENDING) { - // noop - } else if (hasCallback && succeeded) { - $$$internal$$resolve(promise, value); - } else if (failed) { - $$$internal$$reject(promise, error); - } else if (settled === $$$internal$$FULFILLED) { - $$$internal$$fulfill(promise, value); - } else if (settled === $$$internal$$REJECTED) { - $$$internal$$reject(promise, value); - } - } - - function $$$internal$$initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value){ - $$$internal$$resolve(promise, value); - }, function rejectPromise(reason) { - $$$internal$$reject(promise, reason); - }); - } catch(e) { - $$$internal$$reject(promise, e); - } - } - - function $$$enumerator$$makeSettledResult(state, position, value) { - if (state === $$$internal$$FULFILLED) { - return { - state: 'fulfilled', - value: value - }; - } else { - return { - state: 'rejected', - reason: value - }; - } - } - - function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) { - this._instanceConstructor = Constructor; - this.promise = new Constructor($$$internal$$noop, label); - this._abortOnReject = abortOnReject; - - if (this._validateInput(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; - - this._init(); - - if (this.length === 0) { - $$$internal$$fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - $$$internal$$fulfill(this.promise, this._result); - } - } - } else { - $$$internal$$reject(this.promise, this._validationError()); - } - } - - $$$enumerator$$Enumerator.prototype._validateInput = function(input) { - return $$utils$$isArray(input); - }; - - $$$enumerator$$Enumerator.prototype._validationError = function() { - return new Error('Array Methods must be provided an Array'); - }; - - $$$enumerator$$Enumerator.prototype._init = function() { - this._result = new Array(this.length); - }; - - var $$$enumerator$$default = $$$enumerator$$Enumerator; - - $$$enumerator$$Enumerator.prototype._enumerate = function() { - var length = this.length; - var promise = this.promise; - var input = this._input; - - for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { - this._eachEntry(input[i], i); - } - }; - - $$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { - var c = this._instanceConstructor; - if ($$utils$$isMaybeThenable(entry)) { - if (entry.constructor === c && entry._state !== $$$internal$$PENDING) { - entry._onerror = null; - this._settledAt(entry._state, i, entry._result); - } else { - this._willSettleAt(c.resolve(entry), i); - } - } else { - this._remaining--; - this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry); - } - }; - - $$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { - var promise = this.promise; - - if (promise._state === $$$internal$$PENDING) { - this._remaining--; - - if (this._abortOnReject && state === $$$internal$$REJECTED) { - $$$internal$$reject(promise, value); - } else { - this._result[i] = this._makeResult(state, i, value); - } - } - - if (this._remaining === 0) { - $$$internal$$fulfill(promise, this._result); - } - }; - - $$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) { - return value; - }; - - $$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { - var enumerator = this; - - $$$internal$$subscribe(promise, undefined, function(value) { - enumerator._settledAt($$$internal$$FULFILLED, i, value); - }, function(reason) { - enumerator._settledAt($$$internal$$REJECTED, i, reason); - }); - }; - - var $$promise$all$$default = function all(entries, label) { - return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise; - }; - - var $$promise$race$$default = function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor($$$internal$$noop, label); - - if (!$$utils$$isArray(entries)) { - $$$internal$$reject(promise, new TypeError('You must pass an array to race.')); - return promise; - } - - var length = entries.length; - - function onFulfillment(value) { - $$$internal$$resolve(promise, value); - } - - function onRejection(reason) { - $$$internal$$reject(promise, reason); - } - - for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { - $$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); - } - - return promise; - }; - - var $$promise$resolve$$default = function resolve(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor($$$internal$$noop, label); - $$$internal$$resolve(promise, object); - return promise; - }; - - var $$promise$reject$$default = function reject(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor($$$internal$$noop, label); - $$$internal$$reject(promise, reason); - return promise; - }; - - var $$es6$promise$promise$$counter = 0; - - function $$es6$promise$promise$$needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); - } - - function $$es6$promise$promise$$needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); - } - - var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise; - - /** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise’s eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - var promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - var xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class Promise - @param {function} resolver - Useful for tooling. - @constructor - */ - function $$es6$promise$promise$$Promise(resolver) { - this._id = $$es6$promise$promise$$counter++; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - if ($$$internal$$noop !== resolver) { - if (!$$utils$$isFunction(resolver)) { - $$es6$promise$promise$$needsResolver(); - } - - if (!(this instanceof $$es6$promise$promise$$Promise)) { - $$es6$promise$promise$$needsNew(); - } - - $$$internal$$initializePromise(this, resolver); - } - } - - $$es6$promise$promise$$Promise.all = $$promise$all$$default; - $$es6$promise$promise$$Promise.race = $$promise$race$$default; - $$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default; - $$es6$promise$promise$$Promise.reject = $$promise$reject$$default; - - $$es6$promise$promise$$Promise.prototype = { - constructor: $$es6$promise$promise$$Promise, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - var result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - - Promise Example; - - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - - Advanced Example - -------------- - - Synchronous Example - - ```javascript - var author, books; - - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - - function foundBooks(books) { - - } - - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfilled - @param {Function} onRejected - Useful for tooling. - @return {Promise} - */ - then: function(onFulfillment, onRejection) { - var parent = this; - var state = parent._state; - - if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) { - return this; - } - - var child = new this.constructor($$$internal$$noop); - var result = parent._result; - - if (state) { - var callback = arguments[state - 1]; - $$asap$$default(function(){ - $$$internal$$invokeCallback(state, child, callback, result); - }); - } else { - $$$internal$$subscribe(parent, child, onFulfillment, onRejection); - } - - return child; - }, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - Useful for tooling. - @return {Promise} - */ - 'catch': function(onRejection) { - return this.then(null, onRejection); - } - }; - - var $$es6$promise$polyfill$$default = function polyfill() { - var local; - - if (typeof global !== 'undefined') { - local = global; - } else if (typeof window !== 'undefined' && window.document) { - local = window; - } else { - local = self; - } - - var es6PromiseSupport = - "Promise" in local && - // Some of these methods are missing from - // Firefox/Chrome experimental implementations - "resolve" in local.Promise && - "reject" in local.Promise && - "all" in local.Promise && - "race" in local.Promise && - // Older version of the spec had a resolver object - // as the arg rather than a function - (function() { - var resolve; - new local.Promise(function(r) { resolve = r; }); - return $$utils$$isFunction(resolve); - }()); - - if (!es6PromiseSupport) { - local.Promise = $$es6$promise$promise$$default; - } - }; - - var es6$promise$umd$$ES6Promise = { - 'Promise': $$es6$promise$promise$$default, - 'polyfill': $$es6$promise$polyfill$$default - }; - - /* global define:true module:true window: true */ - if (typeof define === 'function' && define['amd']) { - define(function() { return es6$promise$umd$$ES6Promise; }); - } else if (typeof module !== 'undefined' && module['exports']) { - module['exports'] = es6$promise$umd$$ES6Promise; - } else if (typeof this !== 'undefined') { - this['ES6Promise'] = es6$promise$umd$$ES6Promise; - } -}).call(this); -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":48}],5:[function(require,module,exports){ -(function (__dirname){ -/* - * pkginfo.js: Top-level include for the pkginfo module - * - * (C) 2011, Charlie Robbins - * - */ - -var fs = require('fs'), - path = require('path'); - -// -// ### function pkginfo ([options, 'property', 'property' ..]) -// #### @pmodule {Module} Parent module to read from. -// #### @options {Object|Array|string} **Optional** Options used when exposing properties. -// #### @arguments {string...} **Optional** Specified properties to expose. -// Exposes properties from the package.json file for the parent module on -// it's exports. Valid usage: -// -// `require('pkginfo')()` -// -// `require('pkginfo')('version', 'author');` -// -// `require('pkginfo')(['version', 'author']);` -// -// `require('pkginfo')({ include: ['version', 'author'] });` -// -var pkginfo = module.exports = function (pmodule, options) { - var args = [].slice.call(arguments, 2).filter(function (arg) { - return typeof arg === 'string'; - }); - - // - // **Parse variable arguments** - // - if (Array.isArray(options)) { - // - // If the options passed in is an Array assume that - // it is the Array of properties to expose from the - // on the package.json file on the parent module. - // - options = { include: options }; - } - else if (typeof options === 'string') { - // - // Otherwise if the first argument is a string, then - // assume that it is the first property to expose from - // the package.json file on the parent module. - // - options = { include: [options] }; - } - - // - // **Setup default options** - // - options = options || {}; - - // ensure that includes have been defined - options.include = options.include || []; - - if (args.length > 0) { - // - // If additional string arguments have been passed in - // then add them to the properties to expose on the - // parent module. - // - options.include = options.include.concat(args); - } - - var pkg = pkginfo.read(pmodule, options.dir).package; - Object.keys(pkg).forEach(function (key) { - if (options.include.length > 0 && !~options.include.indexOf(key)) { - return; - } - - if (!pmodule.exports[key]) { - pmodule.exports[key] = pkg[key]; - } - }); - - return pkginfo; -}; - -// -// ### function find (dir) -// #### @pmodule {Module} Parent module to read from. -// #### @dir {string} **Optional** Directory to start search from. -// Searches up the directory tree from `dir` until it finds a directory -// which contains a `package.json` file. -// -pkginfo.find = function (pmodule, dir) { - if (! dir) { - dir = path.dirname(pmodule.filename); - } - - var files = fs.readdirSync(dir); - - if (~files.indexOf('package.json')) { - return path.join(dir, 'package.json'); - } - - if (dir === '/') { - throw new Error('Could not find package.json up from: ' + dir); - } - else if (!dir || dir === '.') { - throw new Error('Cannot find package.json from unspecified directory'); - } - - return pkginfo.find(pmodule, path.dirname(dir)); -}; - -// -// ### function read (pmodule, dir) -// #### @pmodule {Module} Parent module to read from. -// #### @dir {string} **Optional** Directory to start search from. -// Searches up the directory tree from `dir` until it finds a directory -// which contains a `package.json` file and returns the package information. -// -pkginfo.read = function (pmodule, dir) { - dir = pkginfo.find(pmodule, dir); - - var data = fs.readFileSync(dir).toString(); - - return { - dir: dir, - package: JSON.parse(data) - }; -}; - -// -// Call `pkginfo` on this module and expose version. -// -pkginfo(module, { - dir: __dirname, - include: ['version'], - target: pkginfo -}); -}).call(this,"/node_modules/jsonld/node_modules/pkginfo/lib") -},{"fs":33,"path":47}],6:[function(require,module,exports){ -// Replace local require by a lazy loader -var globalRequire = require; -require = function () {}; - -// Expose submodules -var exports = module.exports = { - Lexer: require('./lib/N3Lexer'), - Parser: require('./lib/N3Parser'), - Writer: require('./lib/N3Writer'), - Store: require('./lib/N3Store'), - StreamParser: require('./lib/N3StreamParser'), - StreamWriter: require('./lib/N3StreamWriter'), - Util: require('./lib/N3Util'), -}; - -// Load submodules on first access -Object.keys(exports).forEach(function (submodule) { - Object.defineProperty(exports, submodule, { - configurable: true, - enumerable: true, - get: function () { - delete exports[submodule]; - return exports[submodule] = globalRequire('./lib/N3' + submodule); - }, - }); -}); - -},{"./lib/N3Lexer":7,"./lib/N3Parser":8,"./lib/N3Store":9,"./lib/N3StreamParser":10,"./lib/N3StreamWriter":11,"./lib/N3Util":12,"./lib/N3Writer":13}],7:[function(require,module,exports){ -// **N3Lexer** tokenizes N3 documents. -var fromCharCode = String.fromCharCode; -var immediately = typeof setImmediate === 'function' ? setImmediate : - function setImmediate(func) { setTimeout(func, 0); }; - -// Regular expression and replacement string to escape N3 strings. -// Note how we catch invalid unicode sequences separately (they will trigger an error). -var escapeSequence = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{8})|\\[uU]|\\(.)/g; -var escapeReplacements = { '\\': '\\', "'": "'", '"': '"', - 'n': '\n', 'r': '\r', 't': '\t', 'f': '\f', 'b': '\b', - '_': '_', '~': '~', '.': '.', '-': '-', '!': '!', '$': '$', '&': '&', - '(': '(', ')': ')', '*': '*', '+': '+', ',': ',', ';': ';', '=': '=', - '/': '/', '?': '?', '#': '#', '@': '@', '%': '%' }; -var illegalIriChars = /[\x00-\x20<>\\"\{\}\|\^\`]/; - -// ## Constructor -function N3Lexer(options) { - if (!(this instanceof N3Lexer)) - return new N3Lexer(options); - - // In line mode (N-Triples or N-Quads), only simple features may be parsed - if (options && options.lineMode) { - // Don't tokenize special literals - this._tripleQuotedString = this._number = this._boolean = /$0^/; - // Swap the tokenize method for a restricted version - var self = this; - this._tokenize = this.tokenize; - this.tokenize = function (input, callback) { - this._tokenize(input, function (error, token) { - if (!error && /IRI|prefixed|literal|langcode|type|\.|eof/.test(token.type)) - callback && callback(error, token); - else - callback && callback(error || self._syntaxError(token.type, callback = null)); - }); - }; - } -} - -N3Lexer.prototype = { - // ## Regular expressions - // It's slightly faster to have these as properties than as in-scope variables. - - _iri: /^<((?:[^>\\]|\\[uU])+)>/, // IRI with escape sequences; needs sanity check after unescaping - _unescapedIri: /^<([^\x00-\x20<>\\"\{\}\|\^\`]*)>/, // IRI without escape sequences; no unescaping - _unescapedString: /^"[^"\\]+"(?=[^"\\])/, // non-empty string without escape sequences - _singleQuotedString: /^"[^"\\]*(?:\\.[^"\\]*)*"(?=[^"\\])|^'[^'\\]*(?:\\.[^'\\]*)*'(?=[^'\\])/, - _tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/, - _langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i, - _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<])/, - _prefixed: /^((?:[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])*)?:((?:(?:[0-:A-Z_a-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-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-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]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-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]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?=\.?[,;\s#()\[\]\{\}"'<])/, - _blank: /^_:((?:[0-9A-Z_a-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#()\[\]\{\}"'<])/, - _number: /^[\-+]?(?:\d+\.?\d*([eE](?:[\-\+])?\d+)|\d*\.?\d+)(?=[.,;:\s#()\[\]\{\}"'<])/, - _boolean: /^(?:true|false)(?=[.,;:\s#()\[\]\{\}"'<])/, - _keyword: /^@[a-z]+(?=[\s#<:])/, - _sparqlKeyword: /^(?:PREFIX|BASE|GRAPH)(?=[\s#<:])/i, - _shortPredicates: /^a(?=\s+|<)/, - _newline: /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/, - _whitespace: /^[ \t]+/, - _endOfFile: /^(?:#[^\n\r]*)?$/, - - // ## Private methods - - // ### `_tokenizeToEnd` tokenizes as for as possible, emitting tokens through the callback. - _tokenizeToEnd: function (callback, inputFinished) { - // Continue parsing as far as possible; the loop will return eventually. - var input = this._input; - while (true) { - // Count and skip whitespace lines. - var whiteSpaceMatch; - while (whiteSpaceMatch = this._newline.exec(input)) - input = input.substr(whiteSpaceMatch[0].length, input.length), this._line++; - // Skip whitespace on current line. - if (whiteSpaceMatch = this._whitespace.exec(input)) - input = input.substr(whiteSpaceMatch[0].length, input.length); - - // Stop for now if we're at the end. - if (this._endOfFile.test(input)) { - // If the input is finished, emit EOF. - if (inputFinished) - callback(input = null, { line: this._line, type: 'eof', value: '', prefix: '' }); - return this._input = input; - } - - // Look for specific token types based on the first character. - var line = this._line, type = '', value = '', prefix = '', - firstChar = input[0], match = null, matchLength = 0, unescaped, inconclusive = false; - switch (firstChar) { - case '^': - // Try to match a type. - if (input.length === 1) break; - else if (input[1] !== '^') return reportSyntaxError(this); - this._prevTokenType = '^'; - // Move to type IRI or prefixed name. - input = input.substr(2); - if (input[0] !== '<') { - inconclusive = true; - break; - } - // Fall through in case the type is an IRI. - - case '<': - // Try to find a full IRI without escape sequences. - if (match = this._unescapedIri.exec(input)) { - type = 'IRI'; - value = match[1]; - } - // Try to find a full IRI with escape sequences. - else if (match = this._iri.exec(input)) { - unescaped = this._unescape(match[1]); - if (unescaped === null || illegalIriChars.test(unescaped)) - return reportSyntaxError(this); - type = 'IRI'; - value = unescaped; - } - break; - - case '_': - // Try to find a blank node. Since it can contain (but not end with) a dot, - // we always need a non-dot character before deciding it is a prefixed name. - // Therefore, try inserting a space if we're at the end of the input. - if ((match = this._blank.exec(input)) || - inputFinished && (match = this._blank.exec(input + ' '))) { - type = 'prefixed'; - prefix = '_'; - value = match[1]; - } - break; - - case '"': - case "'": - // Try to find a non-empty double-quoted literal without escape sequences. - if (match = this._unescapedString.exec(input)) { - type = 'literal'; - value = match[0]; - } - // 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, '"'); - } - // 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, '"'); - } - break; - - case '@': - // Try to find a language code. - if (this._prevTokenType === 'literal' && (match = this._langcode.exec(input))) { - type = 'langcode'; - value = match[1]; - } - // Try to find a keyword. - else if (match = this._keyword.exec(input)) { - type = match[0]; - } - break; - - case '.': - // Try to find a dot as punctuation. - if (input.length === 1 ? inputFinished : (input[1] < '0' || input[1] > '9')) { - type = '.'; - matchLength = 1; - break; - } - // Fall through to numerical case (could be a decimal dot). - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - // Try to find a number. - if (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')); - } - break; - - case 'B': - case 'b': - case 'p': - case 'P': - case 'G': - case 'g': - // Try to find a SPARQL-style keyword. - if (match = this._sparqlKeyword.exec(input)) - type = match[0].toUpperCase(); - else - inconclusive = true; - break; - - case 'f': - case 't': - // Try to match a boolean. - if (match = this._boolean.exec(input)) { - type = 'literal'; - value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#boolean'; - } - else - inconclusive = true; - break; - - case 'a': - // Try to find an abbreviated predicate. - if (match = this._shortPredicates.exec(input)) { - type = 'abbreviation'; - value = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; - } - else - inconclusive = true; - break; - - case ',': - case ';': - case '[': - case ']': - case '(': - case ')': - case '{': - case '}': - // The next token is punctuation - matchLength = 1; - type = firstChar; - break; - - default: - inconclusive = true; - } - - // Some first characters do not allow an immediate decision, so inspect more. - if (inconclusive) { - // Try to find a prefix. - if ((this._prevTokenType === '@prefix' || this._prevTokenType === 'PREFIX') && - (match = this._prefix.exec(input))) { - type = 'prefix'; - value = match[1] || ''; - } - // Try to find a prefixed name. Since it can contain (but not end with) a dot, - // we always need a non-dot character before deciding it is a prefixed name. - // Therefore, try inserting a space if we're at the end of the input. - else if ((match = this._prefixed.exec(input)) || - inputFinished && (match = this._prefixed.exec(input + ' '))) { - type = 'prefixed'; - prefix = match[1] || ''; - value = this._unescape(match[2]); - } - } - - // A type token is special: it can only be emitted after an IRI or prefixed name is read. - if (this._prevTokenType === '^') - type = (type === 'IRI' || type === 'prefixed') ? 'type' : ''; - - // What if nothing of the above was found? - if (!type) { - // We could be in streaming mode, and then we just wait for more input to arrive. - // Otherwise, a syntax error has occurred in the input. - // One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal). - if (inputFinished || (!/^'''|^"""/.test(input) && /\n|\r/.test(input))) - return reportSyntaxError(this); - else - return this._input = input; - } - - // Emit the parsed token. - callback(null, { line: line, type: type, value: value, prefix: prefix }); - this._prevTokenType = type; - - // Advance to next part to tokenize. - input = input.substr(matchLength || match[0].length, input.length); - } - - // Signals the syntax error through the callback - function reportSyntaxError(self) { callback(self._syntaxError(/^\S*/.exec(input)[0])); } - }, - - // ### `_unescape` replaces N3 escape codes by their corresponding characters. - _unescape: function (item) { - try { - return item.replace(escapeSequence, function (sequence, unicode4, unicode8, escapedChar) { - var charCode; - if (unicode4) { - charCode = parseInt(unicode4, 16); - if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance - return fromCharCode(charCode); - } - else if (unicode8) { - charCode = parseInt(unicode8, 16); - if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance - if (charCode <= 0xFFFF) return fromCharCode(charCode); - return fromCharCode(0xD800 + ((charCode -= 0x10000) / 0x400), 0xDC00 + (charCode & 0x3FF)); - } - else { - var replacement = escapeReplacements[escapedChar]; - if (!replacement) - throw new Error(); - return replacement; - } - }); - } - catch (error) { return null; } - }, - - // ### `_syntaxError` creates a syntax error for the given issue - _syntaxError: function (issue) { - this._input = null; - return new Error('Syntax error: unexpected "' + issue + '" on line ' + this._line + '.'); - }, - - - // ## Public methods - - // ### `tokenize` starts the transformation of an N3 document into an array of tokens. - // The input can be a string or a stream. - tokenize: function (input, callback) { - var self = this; - this._line = 1; - - // If the input is a string, continuously emit tokens through the callback until the end. - if (typeof input === 'string') { - this._input = input; - immediately(function () { self._tokenizeToEnd(callback, true); }); - } - // Otherwise, the input will be streamed. - 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); - } - } - - // 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); - } - } - }, -}; - -// ## Exports - -// Export the `N3Lexer` class as a whole. -module.exports = N3Lexer; - -},{}],8:[function(require,module,exports){ -// **N3Parser** parses N3 documents. -var N3Lexer = require('./N3Lexer'); - -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 absoluteIRI = /:/, - documentPart = /[^\/]*$/, - rootIRI = /^(?:[^:]+:\/*)?[^\/]*/; - -// The next ID for new blank nodes -var blankNodePrefix = 0, blankNodeCount = 0; - -// ## Constructor -function N3Parser(options) { - if (!(this instanceof N3Parser)) - return new N3Parser(options); - this._tripleStack = []; - this._graph = null; - - // Set the document IRI. - options = options || {}; - if (!options.documentIRI) { - this._baseIRI = null; - this._baseIRIPath = null; - } - else { - if (options.documentIRI.indexOf('#') > 0) - throw new Error('Invalid document IRI'); - this._baseIRI = options.documentIRI; - this._baseIRIPath = this._baseIRI.replace(documentPart, ''); - this._baseIRIRoot = this._baseIRI.match(rootIRI)[0]; - } - - // Set supported features depending on the format. - var format = (typeof options.format === 'string') && options.format.match(/\w*$/)[0].toLowerCase(), - isTurtle = format === 'turtle', isTriG = format === 'trig', - isNTriples = /triple/.test(format), isNQuads = /quad/.test(format), - isLineMode = isNTriples || isNQuads; - if (!(this._supportsNamedGraphs = !isTurtle)) - this._readPredicateOrNamedGraph = this._readPredicate; - this._supportsQuads = !(isTurtle || isTriG || isNTriples); - // Disable relative IRIs in N-Triples or N-Quads mode - if (isLineMode) { - this._baseIRI = ''; - this._resolveIRI = function (token) { - this._error('Disallowed relative IRI', token); - return this._callback = noop, this._subject = null; - }; - } - this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode }); -} - -// ## Private class methods - -// ### `_resetBlankNodeIds` restarts blank node identification. -N3Parser._resetBlankNodeIds = function () { - blankNodePrefix = blankNodeCount = 0; -}; - -N3Parser.prototype = { - // ## Private methods - - // ### `_readInTopContext` reads a token when in the top context. - _readInTopContext: function (token) { - switch (token.type) { - // If an EOF token arrives in the top context, signal that we're done. - case 'eof': - if (this._graph !== null) - return this._error('Unclosed graph', token); - delete this._prefixes._; - return this._callback(null, null, this._prefixes); - // It could be a prefix declaration. - case '@prefix': - this._sparqlStyle = false; - return this._readPrefix; - case 'PREFIX': - this._sparqlStyle = true; - return this._readPrefix; - // It could be a base declaration. - case '@base': - this._sparqlStyle = false; - return this._readBaseIRI; - case 'BASE': - this._sparqlStyle = true; - return this._readBaseIRI; - // It could be a graph. - case '{': - if (this._supportsNamedGraphs) { - this._graph = ''; - this._subject = null; - return this._readSubject; - } - case 'GRAPH': - if (this._supportsNamedGraphs) { - return this._readNamedGraphLabel; - } - // Otherwise, the next token must be a subject. - default: - return this._readSubject(token); - } - }, - - // ### `_readSubject` reads a triple's subject. - _readSubject: function (token) { - this._predicate = null; - switch (token.type) { - case 'IRI': - if (this._baseIRI === null || absoluteIRI.test(token.value)) - this._subject = token.value; - else - this._subject = this._resolveIRI(token); - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._subject = prefix + token.value; - break; - case '[': - // Start a new triple with a new blank node as subject. - this._subject = '_:b' + blankNodeCount++; - this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); - return this._readBlankNodeHead; - case '(': - // Start a new list - this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); - this._subject = null; - return this._readListItem; - case '}': - return this._readPunctuation(token); - default: - return this._error('Expected subject but got ' + token.type, token); - } - // The next token must be a predicate, - // or, if the subject was actually a graph IRI, a named graph. - return this._readPredicateOrNamedGraph; - }, - - // ### `_readPredicate` reads a triple's predicate. - _readPredicate: function (token) { - switch (token.type) { - case 'IRI': - case 'abbreviation': - if (this._baseIRI === null || absoluteIRI.test(token.value)) - this._predicate = token.value; - else - this._predicate = this._resolveIRI(token); - break; - case 'prefixed': - if (token.prefix === '_') { - return this._error('Disallowed blank node as predicate', token); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._predicate = prefix + token.value; - } - break; - case '.': - case ']': - case '}': - // Expected predicate didn't come, must have been trailing semicolon. - if (this._predicate === null) - return this._error('Unexpected ' + token.type, token); - this._subject = null; - return this._readBlankNodeTail(token); - case ';': - // Extra semicolons can be safely ignored - return this._readPredicate; - default: - return this._error('Expected predicate to follow "' + this._subject + '"', token); - } - // The next token must be an object. - return this._readObject; - }, - - // ### `_readObject` reads a triple's object. - _readObject: function (token) { - switch (token.type) { - case 'IRI': - if (this._baseIRI === null || absoluteIRI.test(token.value)) - this._object = token.value; - else - this._object = this._resolveIRI(token); - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._object = prefix + token.value; - break; - case 'literal': - this._object = token.value; - return this._readDataTypeOrLang; - case '[': - // Start a new triple with a new blank node as subject. - var blank = '_:b' + blankNodeCount++; - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); - this._subject = blank; - return this._readBlankNodeHead; - case '(': - // Start a new list - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Expected object to follow "' + this._predicate + '"', token); - } - return this._getTripleEndReader(); - }, - - // ### `_readPredicateOrNamedGraph` reads a triple's predicate, or a named graph. - _readPredicateOrNamedGraph: function (token) { - return token.type === '{' ? this._readGraph(token) : this._readPredicate(token); - }, - - // ### `_readGraph` reads a graph. - _readGraph: function (token) { - if (token.type !== '{') - return this._error('Expected graph but got ' + token.type, token); - // The "subject" we read is actually the GRAPH's label - this._graph = this._subject, this._subject = null; - return this._readSubject; - }, - - // ### `_readBlankNodeHead` reads the head of a blank node. - _readBlankNodeHead: function (token) { - if (token.type === ']') { - this._subject = null; - return this._readBlankNodeTail(token); - } - this._predicate = null; - return this._readPredicate(token); - }, - - // ### `_readBlankNodeTail` reads the end of a blank node. - _readBlankNodeTail: function (token) { - if (token.type !== ']') - return this._readPunctuation(token); - - // Store blank node triple. - if (this._subject !== null) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: this._graph || '' }); - - // Restore parent triple that contains the blank node. - var triple = this._tripleStack.pop(); - this._subject = triple.subject; - // Was the blank node the object? - if (triple.object !== null) { - // Restore predicate and object as well, and continue by reading punctuation. - this._predicate = triple.predicate; - this._object = triple.object; - return this._getTripleEndReader(); - } - // The blank node was the subject, so continue reading the predicate. - // If the blank node didn't contain any predicates, it could also be the label of a named graph. - return this._predicate !== null ? this._readPredicate : this._readPredicateOrNamedGraph; - }, - - // ### `_readDataTypeOrLang` reads an _optional_ data type or language. - _readDataTypeOrLang: function (token) { - switch (token.type) { - case 'type': - var value; - if (token.prefix === '') { - if (this._baseIRI === null || absoluteIRI.test(token.value)) - value = token.value; - else - value = this._resolveIRI(token); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - value = prefix + token.value; - } - this._object += '^^' + value; - return this._getTripleEndReader(); - case 'langcode': - this._object += '@' + token.value.toLowerCase(); - return this._getTripleEndReader(); - default: - return this._getTripleEndReader().call(this, token); - } - }, - - // ### `_readListItem` reads items from a list. - _readListItem: function (token) { - var item = null, // The actual list item. - itemHead = null, // The head of the rdf:first predicate. - prevItemHead = this._subject, // The head of the previous rdf:first predicate. - stack = this._tripleStack, // The stack of triples part of recursion (lists, blanks, etc.). - parentTriple = stack[stack.length - 1], // The triple containing the current list. - next = this._readListItem; // The next function to execute. - - switch (token.type) { - case 'IRI': - item = token.value; - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - item = prefix + token.value; - break; - case 'literal': - item = token.value; - next = this._readDataTypeOrLang; - break; - case '[': - // Stack the current list triple and start a new triple with a blank node as subject. - itemHead = '_:b' + blankNodeCount++; - item = '_:b' + blankNodeCount++; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); - this._subject = item; - next = this._readBlankNodeHead; - break; - case '(': - // Stack the current list triple and start a new list - itemHead = '_:b' + blankNodeCount++; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); - this._subject = null; - next = this._readListItem; - break; - case ')': - // Restore the parent triple. - stack.pop(); - // If this list is contained within a parent list, return the membership triple here. - // This will be ` rdf:first .`. - if (stack.length !== 0 && stack[stack.length - 1].type === 'list') - this._callback(null, { subject: parentTriple.subject, - predicate: parentTriple.predicate, - object: parentTriple.object, - graph: this._graph || '' }); - // Restore the parent triple's subject. - this._subject = parentTriple.subject; - // Was this list in the parent triple's subject? - if (parentTriple.predicate === null) { - // The next token is the predicate. - next = this._readPredicate; - // Skip writing the list tail if this was an empty list. - if (parentTriple.subject === RDF_NIL) - return next; - } - // The list was in the parent triple's object. - else { - // Restore the parent triple's predicate and object as well. - this._predicate = parentTriple.predicate; - this._object = parentTriple.object; - next = this._getTripleEndReader(); - // Skip writing the list tail if this was an empty list. - if (parentTriple.object === RDF_NIL) - return next; - } - // Close the list by making the item head nil. - itemHead = RDF_NIL; - break; - default: - return this._error('Expected list item instead of "' + token.type + '"', token); - } - - // Create a new blank node if no item head was assigned yet. - if (itemHead === null) - this._subject = itemHead = '_:b' + blankNodeCount++; - - // Is this the first element of the list? - if (prevItemHead === null) { - // This list is either the object or the subject. - if (parentTriple.object === RDF_NIL) - parentTriple.object = itemHead; - else - parentTriple.subject = itemHead; - } - else { - // The rest of the list is in the current head. - this._callback(null, { subject: prevItemHead, - predicate: RDF_REST, - object: itemHead, - graph: this._graph || '' }); - } - // Add the item's value. - if (item !== null) - this._callback(null, { subject: itemHead, - predicate: RDF_FIRST, - object: item, - graph: this._graph || '' }); - return next; - }, - - // ### `_readPunctuation` reads punctuation between triples or triple parts. - _readPunctuation: function (token) { - var next, subject = this._subject, graph = this._graph; - switch (token.type) { - // A closing brace ends a graph - case '}': - if (this._graph === null) - return this._error('Unexpected graph closing', token); - this._graph = null; - // A dot just ends the statement, without sharing anything with the next. - case '.': - this._subject = null; - next = this._readInTopContext; - break; - // Semicolon means the subject is shared; predicate and object are different. - case ';': - next = this._readPredicate; - break; - // Comma means both the subject and predicate are shared; the object is different. - case ',': - next = this._readObject; - break; - // An IRI means this is a quad (only allowed if not already inside a graph). - case 'IRI': - if (this._supportsQuads && this._graph === null) { - if (this._baseIRI === null || absoluteIRI.test(token.value)) - graph = token.value; - else - graph = this._resolveIRI(token); - subject = this._subject; - next = this._readQuadPunctuation; - break; - } - // An prefixed name means this is a quad (only allowed if not already inside a graph). - case 'prefixed': - if (this._supportsQuads && this._graph === null) { - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - graph = prefix + token.value; - next = this._readQuadPunctuation; - break; - } - default: - return this._error('Expected punctuation to follow "' + this._object + '"', token); - } - // A triple has been completed now, so return it. - if (subject !== null) - this._callback(null, { subject: subject, - predicate: this._predicate, - object: this._object, - graph: graph || '' }); - return next; - }, - - // ### `_readQuadPunctuation` reads punctuation after a quad. - _readQuadPunctuation: function (token) { - if (token.type !== '.') - return this._error('Expected dot to follow quad', token); - return this._readInTopContext; - }, - - // ### `_readPrefix` reads the prefix of a prefix declaration. - _readPrefix: function (token) { - if (token.type !== 'prefix') - return this._error('Expected prefix to follow @prefix', token); - this._prefix = token.value; - return this._readPrefixIRI; - }, - - // ### `_readPrefixIRI` reads the IRI of a prefix declaration. - _readPrefixIRI: function (token) { - if (token.type !== 'IRI') - return this._error('Expected IRI to follow prefix "' + this._prefix + ':"', token); - var prefixIRI; - if (this._baseIRI === null || absoluteIRI.test(token.value)) - prefixIRI = token.value; - else - prefixIRI = this._resolveIRI(token); - this._prefixes[this._prefix] = prefixIRI; - this._prefixCallback(this._prefix, prefixIRI); - return this._readDeclarationPunctuation; - }, - - // ### `_readBaseIRI` reads the IRI of a base declaration. - _readBaseIRI: function (token) { - if (token.type !== 'IRI') - return this._error('Expected IRI to follow base declaration', token); - if (token.value.indexOf('#') > 0) - return this._error('Invalid base IRI', token); - if (this._baseIRI === null || absoluteIRI.test(token.value)) - this._baseIRI = token.value; - else - this._baseIRI = this._resolveIRI(token); - this._baseIRIPath = this._baseIRI.replace(documentPart, ''); - this._baseIRIRoot = this._baseIRI.match(rootIRI)[0]; - return this._readDeclarationPunctuation; - }, - - // ### `_readNamedGraphLabel` reads the label of a named graph. - _readNamedGraphLabel: function (token) { - switch (token.type) { - case 'IRI': - case 'prefixed': - return this._readSubject(token), this._readGraph; - case '[': - return this._readNamedGraphBlankLabel; - default: - return this._error('Invalid graph label', token); - } - }, - - // ### `_readNamedGraphLabel` reads a blank node label of a named graph. - _readNamedGraphBlankLabel: function (token) { - if (token.type !== ']') - return this._error('Invalid graph label', token); - this._subject = '_:b' + blankNodeCount++; - return this._readGraph; - }, - - // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. - _readDeclarationPunctuation: function (token) { - // SPARQL-style declarations don't have punctuation. - if (this._sparqlStyle) - return this._readInTopContext(token); - - if (token.type !== '.') - return this._error('Expected declaration to end with a dot', token); - return this._readInTopContext; - }, - - // ### `_getTripleEndReader` gets the next reader function at the end of a triple. - _getTripleEndReader: function () { - var stack = this._tripleStack; - if (stack.length === 0) - return this._readPunctuation; - - switch (stack[stack.length - 1].type) { - case 'blank': - return this._readBlankNodeTail; - case 'list': - return this._readListItem; - } - }, - - // ### `_error` emits an error message through the callback. - _error: function (message, token) { - this._callback(new Error(message + ' at line ' + token.line + '.')); - }, - - // ### `_resolveIRI` resolves an IRI token against the base path - _resolveIRI: function (token) { - var iri = token.value; - switch (iri[0]) { - // An empty relative IRI indicates the base IRI - case undefined: - return this._baseIRI; - // Resolve relative fragment IRIs against the base IRI - case '#': - return this._baseIRI + iri; - // Resolve relative query string IRIs by replacing the query string - case '?': - return this._baseIRI.replace(/(?:\?.*)?$/, iri); - // Resolve root relative IRIs at the root of the base IRI - case '/': - return this._baseIRIRoot + iri; - // Resolve all other IRIs at the base IRI's path - default: - return this._baseIRIPath + iri; - } - }, - - // ## Public methods - - // ### `parse` parses the N3 input and emits each parsed triple through the callback. - parse: function (input, tripleCallback, prefixCallback) { - // The read callback is the next function to be executed when a token arrives. - // We start reading in the top context. - this._readCallback = this._readInTopContext; - this._prefixes = Object.create(null); - this._prefixes._ = '_:b' + blankNodePrefix++ + '_'; - - // If the input argument is not given, shift parameters - if (typeof input === 'function') - prefixCallback = tripleCallback, tripleCallback = input, input = null; - - // Set the triple and prefix callbacks. - 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) - 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; - } - } -}; - -// The empty function -function noop() {} - -// ## Exports - -// Export the `N3Parser` class as a whole. -module.exports = N3Parser; - -},{"./N3Lexer":7}],9:[function(require,module,exports){ -// **N3Store** objects store N3 triples by graph in memory. - -var expandPrefixedName = require('./N3Util').expandPrefixedName; - -// ## Constructor -function N3Store(triples, options) { - if (!(this instanceof N3Store)) - return new N3Store(triples, options); - - // The number of triples is initially zero. - this._size = 0; - // `_graphs` contains subject, predicate, and object indexes per graph. - this._graphs = Object.create(null); - // `_entities` maps entities such as `http://xmlns.com/foaf/0.1/name` to numbers. - // This saves memory, since only the numbers have to be stored in `_graphs`. - this._entities = Object.create(null); - this._entities['><'] = 0; // Dummy entry, so the first actual key is non-zero - this._entityCount = 0; - // `_blankNodeIndex` is the index of the last created blank node that was automatically named - this._blankNodeIndex = 0; - - // Shift parameters if `triples` is not given - if (!options && triples && !triples[0]) - options = triples, triples = null; - - // Add triples and prefixes if passed - this._prefixes = Object.create(null); - if (options && options.prefixes) - this.addPrefixes(options.prefixes); - if (triples) - this.addTriples(triples); -} - -N3Store.prototype = { - // ## Public properties - - // ### `size` returns the number of triples in the store. - get size() { - // Return the triple count if if was cached. - var size = this._size; - if (size !== null) - return size; - - // Calculate the number of triples by counting to the deepest level. - var graphs = this._graphs, subjects, subject; - for (var graphKey in graphs) - for (var subjectKey in (subjects = graphs[graphKey].subjects)) - for (var predicateKey in (subject = subjects[subjectKey])) - size += Object.keys(subject[predicateKey]).length; - return this._size = size; - }, - - // ## Private methods - - // ### `_addToIndex` adds a triple to a three-layered index. - _addToIndex: function (index0, key0, key1, key2) { - // Create layers as necessary. - var index1 = index0[key0] || (index0[key0] = {}); - var index2 = index1[key1] || (index1[key1] = {}); - // Setting the key to _any_ value signalizes the presence of the triple. - index2[key2] = null; - }, - - // ### `_removeFromIndex` removes a triple from a three-layered index. - _removeFromIndex: function (index0, key0, key1, key2) { - // Remove the triple from the index. - var index1 = index0[key0], index2 = index1[key1], key; - delete index2[key2]; - - // Remove intermediary index layers if they are empty. - for (key in index2) return; - delete index1[key1]; - for (key in index1) return; - delete index0[key0]; - }, - - // ### `_findInIndex` finds a set of triples 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 `null`, 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 - // (for instance: _subject_, _predicate_, and _object_). - // Finally, `graph` will be the graph of the created triples. - _findInIndex: function (index0, key0, key1, key2, name0, name1, name2, graph) { - var results = [], entityKeys = Object.keys(this._entities), tmp, index1, index2; - - // If a key is specified, use only that part of index 0. - if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; - for (var value0 in index0) { - var entity0 = entityKeys[value0]; - - if (index1 = index0[value0]) { - // If a key is specified, use only that part of index 1. - if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; - for (var value1 in index1) { - var entity1 = entityKeys[value1]; - - if (index2 = index1[value1]) { - // If a key is specified, use only that part of index 2, if it exists. - 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]]; - results.push(result); - } - } - } - } - } - return results; - }, - - // ### `_countInIndex` counts matching triples 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 `null`, which is interpreted as a wildcard. - _countInIndex: function (index0, key0, key1, key2) { - var count = 0, tmp, index1, index2; - - // If a key is specified, count only that part of index 0. - if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; - for (var value0 in index0) { - if (index1 = index0[value0]) { - - // If a key is specified, count only that part of index 1. - if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; - for (var value1 in index1) { - if (index2 = index1[value1]) { - // If a key is specified, count the triple if it exists. - if (key2) (key2 in index2) && count++; - // Otherwise, count all triples. - else count += Object.keys(index2).length; - } - } - } - } - return count; - }, - - // ## Public methods - - // ### `addTriple` adds a new N3 triple to the store. - addTriple: function (subject, predicate, object, graph) { - // Shift arguments if a triple object is given instead of components - if (!predicate) - graph = subject.graph, object = subject.object, - predicate = subject.predicate, subject = subject.subject; - - // Find the graph that will contain the triple. - graph = graph || ''; - var graphItem = this._graphs[graph]; - // Create the graph if it doesn't exist yet. - if (!graphItem) { - graphItem = this._graphs[graph] = { - subjects: {}, - predicates: {}, - objects: {} - }; - // Freezing a graph helps subsequent `add` performance, - // and properties will never be modified anyway. - Object.freeze(graphItem); - } - - // Since entities can often be long IRIs, we avoid storing them in every index. - // Instead, we have a separate index that maps entities to numbers, - // which are then used as keys in the other indexes. - var entities = this._entities; - subject = entities[subject] || (entities[subject] = ++this._entityCount); - predicate = entities[predicate] || (entities[predicate] = ++this._entityCount); - object = entities[object] || (entities[object] = ++this._entityCount); - - this._addToIndex(graphItem.subjects, subject, predicate, object); - this._addToIndex(graphItem.predicates, predicate, object, subject); - this._addToIndex(graphItem.objects, object, subject, predicate); - - // The cached triple count is now invalid. - this._size = null; - }, - - // ### `addTriples` adds multiple N3 triples to the store. - addTriples: function (triples) { - for (var i = triples.length - 1; i >= 0; i--) - this.addTriple(triples[i]); - }, - - // ### `addPrefix` adds support for querying with the given prefix - addPrefix: function (prefix, iri) { - this._prefixes[prefix] = iri; - }, - - // ### `addPrefixex` 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. - if (!predicate) - graph = subject.graph, object = subject.object, - predicate = subject.predicate, subject = subject.subject; - graph = graph || ''; - - // Find internal identifiers for all components. - var graphItem, entities = this._entities, graphs = this._graphs; - if (!(subject = entities[subject])) return; - if (!(predicate = entities[predicate])) return; - if (!(object = entities[object])) return; - if (!(graphItem = graphs[graph])) return; - - // Verify that the triple exists. - var subjects, predicates; - if (!(subjects = graphItem.subjects[subject])) return; - if (!(predicates = subjects[predicate])) return; - if (!(object in predicates)) return; - - // Remove it from all indexes. - this._removeFromIndex(graphItem.subjects, subject, predicate, object); - this._removeFromIndex(graphItem.predicates, predicate, object, subject); - this._removeFromIndex(graphItem.objects, object, subject, predicate); - if (this._size !== null) this._size--; - - // Remove the graph if it is empty. - for (subject in graphItem.subjects) return; - delete graphs[graph]; - }, - - // ### `removeTriples` removes multiple N3 triples from the store. - removeTriples: function (triples) { - for (var i = triples.length - 1; i >= 0; i--) - this.removeTriple(triples[i]); - }, - - // ### `find` finds a set of triples matching a pattern, expanding prefixes as necessary. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - find: function (subject, predicate, object, graph) { - var prefixes = this._prefixes; - return this.findByIRI( - expandPrefixedName(subject, prefixes), - expandPrefixedName(predicate, prefixes), - expandPrefixedName(object, prefixes), - expandPrefixedName(graph, prefixes) - ); - }, - - // ### `findByIRI` finds a set of triples matching a pattern. - // Setting `subject`, `predicate`, or `object` to a falsy value means an _anything_ wildcard. - // Setting `graph` to a falsy value means the default graph. - findByIRI: function (subject, predicate, object, graph) { - graph = graph || ''; - var graphItem = this._graphs[graph], entities = this._entities; - - // If the specified graph contain no triples, there are no results. - if (!graphItem) return []; - - // Translate IRIs to internal index keys. - // Optimization: if the entity doesn't exist, no triples with it exist. - if (subject && !(subject = entities[subject])) return []; - if (predicate && !(predicate = entities[predicate])) return []; - if (object && !(object = entities[object])) return []; - - // Choose the optimal index, based on what fields are present - if (subject) { - if (object) - // If subject and object are given, the object index will be the fastest. - return this._findInIndex(graphItem.objects, object, subject, predicate, - 'object', 'subject', 'predicate', graph); - else - // If only subject and possibly predicate are given, the subject index will be the fastest. - return this._findInIndex(graphItem.subjects, subject, predicate, null, - 'subject', 'predicate', 'object', graph); - } - else if (predicate) - // If only predicate and possibly object are given, the predicate index will be the fastest. - return this._findInIndex(graphItem.predicates, predicate, object, null, - 'predicate', 'object', 'subject', graph); - else if (object) - // If only object is given, the object index will be the fastest. - return this._findInIndex(graphItem.objects, object, null, null, - 'object', 'subject', 'predicate', graph); - else - // If nothing is given, iterate subjects and predicates first - return this._findInIndex(graphItem.subjects, null, null, null, - 'subject', 'predicate', 'object', graph); - }, - - // ### `count` returns the number of triples matching a pattern, expanding prefixes as necessary. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - count: function (subject, predicate, object, graph) { - var prefixes = this._prefixes; - return this.countByIRI( - expandPrefixedName(subject, prefixes), - expandPrefixedName(predicate, prefixes), - expandPrefixedName(object, prefixes), - expandPrefixedName(graph, prefixes) - ); - }, - - // ### `countByIRI` returns the number of triples matching a pattern. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - countByIRI: function (subject, predicate, object, graph) { - graph = graph || ''; - var graphItem = this._graphs[graph], entities = this._entities; - - // If the specified graph contain no triples, there are no results. - if (!graphItem) return 0; - - // Translate IRIs to internal index keys. - // Optimization: if the entity doesn't exist, no triples with it exist. - if (subject && !(subject = entities[subject])) return 0; - if (predicate && !(predicate = entities[predicate])) return 0; - if (object && !(object = entities[object])) return 0; - - // Choose the optimal index, based on what fields are present - if (subject) { - if (object) - // If subject and object are given, the object index will be the fastest. - return this._countInIndex(graphItem.objects, object, subject, predicate); - else - // If only subject and possibly predicate are given, the subject index will be the fastest. - return this._countInIndex(graphItem.subjects, subject, predicate, object); - } - else if (predicate) { - // If only predicate and possibly object are given, the predicate index will be the fastest. - return this._countInIndex(graphItem.predicates, predicate, object, subject); - } - else { - // If only object is possibly given, the object index will be the fastest. - return this._countInIndex(graphItem.objects, object, subject, predicate); - } - }, - - // ### `createBlankNode` creates a new blank node, returning its name. - createBlankNode: function (suggestedName) { - var name; - if (suggestedName) { - name = suggestedName = '_:' + suggestedName; - var index = 1; - while (this._entities[name]) - name = suggestedName + index++; - } - else { - do { name = '_:b' + this._blankNodeIndex++; } - while (this._entities[name]); - } - this._entities[name] = this._entityCount++; - return name; - }, -}; - -// ## Exports - -// Export the `N3Store` class as a whole. -module.exports = N3Store; - -},{"./N3Util":12}],10:[function(require,module,exports){ -// **N3StreamParser** parses an N3 stream into a triple stream -var Transform = require('stream').Transform, - util = require('util'), - N3Parser = require('./N3Parser.js'); - -// ## Constructor -function N3StreamParser(options) { - if (!(this instanceof N3StreamParser)) - return new N3StreamParser(options); - - // Initialize Transform base class - Transform.call(this, { decodeStrings: true }); - this._readableState.objectMode = true; - - // Set up parser - var self = this, parser = new N3Parser(options); - parser.parse( - // Handle triples by pushing them down the pipeline - function (error, triple) { - triple && self.push(triple) || - error && self.emit('error', error); - }, - // Emit prefixes through the `prefix` event - this.emit.bind(this, 'prefix')); - - // Implement Transform methods on top of parser - this._transform = function (chunk, encoding, done) { parser.addChunk(chunk); done(); }; - this._flush = function (done) { parser.end(); done(); }; -} -util.inherits(N3StreamParser, Transform); - -// ## Exports -// Export the `N3StreamParser` class as a whole. -module.exports = N3StreamParser; - -},{"./N3Parser.js":8,"stream":64,"util":68}],11:[function(require,module,exports){ -// **N3StreamWriter** serializes a triple stream into an N3 stream -var Transform = require('stream').Transform, - util = require('util'), - N3Writer = require('./N3Writer.js'); - -// ## Constructor -function N3StreamWriter(options) { - if (!(this instanceof N3StreamWriter)) - return new N3StreamWriter(options); - - // Initialize Transform base class - Transform.call(this, { encoding: 'utf8' }); - this._writableState.objectMode = true; - - // Set up writer with a dummy stream object - var self = this; - var writer = new N3Writer({ - write: function (chunk, encoding, callback) { self.push(chunk); callback && callback(); }, - end: function (callback) { self.push(null); callback && callback(); }, - }, options); - - // Implement Transform methods on top of writer - this._transform = function (triple, encoding, done) { writer.addTriple(triple, done); }; - this._flush = function (done) { writer.end(done); }; -} -util.inherits(N3StreamWriter, Transform); - -// ## Exports -// Export the `N3StreamWriter` class as a whole. -module.exports = N3StreamWriter; - -},{"./N3Writer.js":13,"stream":64,"util":68}],12:[function(require,module,exports){ -// **N3Util** provides N3 utility functions - -var XsdString = 'http://www.w3.org/2001/XMLSchema#string'; -var RdfLangString = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'; - -var N3Util = { - // Tests whether the given entity (triple object) represents an IRI in the N3 library - isIRI: function (entity) { - if (!entity) - return entity; - var firstChar = entity[0]; - return firstChar !== '"' && firstChar !== '_'; - }, - - // Tests whether the given entity (triple object) represents a literal in the N3 library - isLiteral: function (entity) { - return entity && entity[0] === '"'; - }, - - // Tests whether the given entity (triple object) represents a blank node in the N3 library - isBlank: function (entity) { - return entity && entity.substr(0, 2) === '_:'; - }, - - // 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]; - }, - - // 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 entity && /^[^:\/"']*:[^:\/"']+$/.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); - if (!match) return prefixedName; - - var prefix = match[1], base = prefixes[prefix], index = match.index; - if (base === undefined) - throw new Error('Unknown prefix: ' + prefix); - - // 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); - }, -}; - -// Add the N3Util functions to the given object or its prototype -function AddN3Util(parent, toPrototype) { - for (var name in N3Util) - if (!toPrototype) - parent[name] = N3Util[name]; - else - parent.prototype[name] = ApplyToThis(N3Util[name]); - - return parent; -} - -// Returns a function that applies `f` to the `this` object -function ApplyToThis(f) { - return function (a) { return f(this, a); }; -} - -// Expose N3Util, attaching all functions to it -module.exports = AddN3Util(AddN3Util); - -},{}],13:[function(require,module,exports){ -// **N3Writer** writes N3 documents. - -// Matches a literal as represented in memory by the N3 library -var N3LiteralMatcher = /^"([^]*)"(?:\^\^(.+)|@([\-a-z]+))?$/i; - -// rdf:type predicate (for 'a' abbreviation) -var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - RDF_TYPE = RDF_PREFIX + 'type'; - -// Characters in literals that require escaping -var escape = /["\\\t\n\r\b\f\u0000-\u0019\ud800-\udbff]/, - escapeAll = /["\\\t\n\r\b\f\u0000-\u0019]|[\ud800-\udbff][\udc00-\udfff]/g, - escapeReplacements = { '\\': '\\\\', '"': '\\"', '\t': '\\t', - '\n': '\\n', '\r': '\\r', '\b': '\\b', '\f': '\\f' }; - -// ## Constructor -function N3Writer(outputStream, options) { - if (!(this instanceof N3Writer)) - return new N3Writer(outputStream, options); - - // Shift arguments if the first argument is not a stream - if (outputStream && typeof outputStream.write !== 'function') - options = outputStream, outputStream = null; - - // If no output stream given, send the output as string through the end callback - if (!outputStream) { - outputStream = this; - this._output = ''; - this.write = function (chunk, encoding, callback) { - this._output += chunk; - callback && callback(); - }; - } - this._outputStream = outputStream; - - // Initialize writer, depending on the format - this._subject = null; - options = options || {}; - if (!(/triple|quad/i).test(options.format)) { - this._graph = ''; - this._prefixIRIs = Object.create(null); - options.prefixes && this.addPrefixes(options.prefixes); - } - else { - this._writeTriple = this._writeTripleLine; - } -} - -N3Writer.prototype = { - // ## Private methods - - // ### `_write` writes the argument to the output stream - _write: function (string, callback) { - this._outputStream.write(string, 'utf8', callback); - }, - - // ### `_writeTriple` writes the triple to the output stream - _writeTriple: function (subject, predicate, object, graph, done) { - try { - // Write the graph's label if it has changed - if (this._graph !== 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._graph = graph, this._subject = null; - } - // Don't repeat the subject if it's the same - if (this._subject === subject) { - // Don't repeat the predicate if it's the same - if (this._predicate === predicate) - this._write(', ' + this._encodeObject(object), done); - // Same subject, different predicate - else - this._write(';\n ' + - this._encodePredicate(this._predicate = predicate) + ' ' + - this._encodeObject(object), done); - } - // Different subject; write the whole triple - else - this._write((this._subject === null ? '' : '.\n') + - this._encodeSubject(this._subject = subject) + ' ' + - this._encodePredicate(this._predicate = predicate) + ' ' + - this._encodeObject(object), done); - } - catch (error) { done && done(error); } - }, - - // ### `_writeTripleLine` writes the triple or quad to the output stream as a single line - _writeTripleLine: function (subject, predicate, object, graph, done) { - // Don't use prefixes - delete this._prefixMatch; - // Write the triple - try { - this._write(this._encodeIriOrBlankNode(subject) + ' ' + - this._encodeIriOrBlankNode(predicate) + ' ' + - this._encodeObject(object) + - (graph ? ' ' + this._encodeIriOrBlankNode(graph) + '.\n' : '.\n'), done); - } - catch (error) { done && done(error); } - }, - - // ### `_encodeIriOrBlankNode` represents an IRI or blank node - _encodeIriOrBlankNode: function (iri) { - // A blank node is represented as-is - if (iri[0] === '_' && iri[1] === ':') return iri; - // Escape special characters - if (escape.test(iri)) - iri = iri.replace(escapeAll, characterReplacer); - // Try to represent the IRI as prefixed name - var prefixMatch = this._prefixRegex.exec(iri); - return prefixMatch ? this._prefixIRIs[prefixMatch[1]] + prefixMatch[2] : '<' + iri + '>'; - }, - - // ### `_encodeLiteral` represents a literal - _encodeLiteral: function (value, type, language) { - // Escape special characters - 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); - else - return '"' + value + '"'; - }, - - // ### `_encodeSubject` represents a subject - _encodeSubject: function (subject) { - if (subject[0] === '"') - throw new Error('A literal as subject is not allowed: ' + 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); - }, - - // ### `_encodeObject` represents an object - _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]); - }, - - // ### `_blockedWrite` replaces `_write` after the writer has been closed - _blockedWrite: function () { - throw new Error('Cannot write because the writer has been closed.'); - }, - - // ### `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 - if (typeof object !== 'string') - this._writeTriple(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); - // The `graph` parameter was provided - else - this._writeTriple(subject, predicate, object, graph, done); - }, - - // ### `addTriples` adds the triples to the output stream - addTriples: function (triples) { - for (var i = 0; i < triples.length; i++) - this.addTriple(triples[i]); - }, - - // ### `addPrefix` adds the prefix to the output stream - addPrefix: function (prefix, iri, done) { - var prefixes = {}; - prefixes[prefix] = iri; - this.addPrefixes(prefixes, done); - }, - - // ### `addPrefixes` adds the prefixes to the output stream - addPrefixes: function (prefixes, done) { - // Add all useful prefixes - var hasPrefixes = false; - for (var prefix in prefixes) { - // Verify whether the prefix can be used and does not exist yet - var iri = prefixes[prefix]; - if (/[#\/]$/.test(iri) && this._prefixIRIs[iri] !== (prefix += ':')) { - hasPrefixes = true; - this._prefixIRIs[iri] = prefix; - // Finish a possible pending triple - if (this._subject !== null) { - this._write(this._graph ? '\n}\n' : '.\n'); - this._subject = null, this._graph = ''; - } - // Write prefix - this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); - } - } - // Recreate the prefix matcher - if (hasPrefixes) { - var prefixIRIs = ''; - for (var prefixIRI in this._prefixIRIs) - prefixIRIs += prefixIRIs ? '|' + prefixIRI : prefixIRI; - prefixIRIs = prefixIRIs.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&'); - this._prefixRegex = new RegExp('^(' + prefixIRIs + ')([a-zA-Z][\\-_a-zA-Z0-9]*)$'); - } - // End a prefix block with a newline - this._write(hasPrefixes ? '\n' : '', done); - }, - - // ### `_prefixRegex` matches an IRI that begins with one of the added prefixes - _prefixRegex: /$0^/, - - // ### `end` signals the end of the output stream - end: function (done) { - // Finish a possible pending triple - if (this._subject !== null) { - this._write(this._graph ? '\n}\n' : '.\n'); - this._subject = null; - } - // Disallow further writing - this._write = this._blockedWrite; - - // If writing to a string instead of an actual stream, send the string - if (this === this._outputStream) - return done && done(null, this._output); - - // Try to end the underlying stream, ensuring done is called exactly one time - var singleDone = done && function () { singleDone = null, done(); }; - // Ending a stream can error - try { this._outputStream.end(singleDone); } - // Execute the callback if it hasn't been executed - catch (error) { singleDone && singleDone(); } - }, -}; - -// Replaces a character by its escaped version -function characterReplacer(character) { - // Replace a single character by its escaped version - var result = escapeReplacements[character]; - if (result === undefined) { - // Replace a single character with its 4-bit unicode escape sequence - if (character.length === 1) { - result = character.charCodeAt(0).toString(16); - result = '\\u0000'.substr(0, 6 - result.length) + result; - } - // Replace a surrogate pair with its 8-bit unicode escape sequence - else { - result = ((character.charCodeAt(0) - 0xD800) * 0x400 + - character.charCodeAt(1) + 0x2400).toString(16); - result = '\\U00000000'.substr(0, 10 - result.length) + result; - } - } - return result; -} - -// ## Exports - -// Export the `N3Writer` class as a whole. -module.exports = N3Writer; - -},{}],14:[function(require,module,exports){ -'use strict'; - -module.exports = require('./lib/core.js') -require('./lib/done.js') -require('./lib/es6-extensions.js') -require('./lib/node-extensions.js') -},{"./lib/core.js":15,"./lib/done.js":16,"./lib/es6-extensions.js":17,"./lib/node-extensions.js":18}],15:[function(require,module,exports){ -'use strict'; - -var asap = require('asap') - -module.exports = Promise; -function Promise(fn) { - if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new') - if (typeof fn !== 'function') throw new TypeError('not a function') - var state = null - var value = null - var deferreds = [] - var self = this - - this.then = function(onFulfilled, onRejected) { - return new self.constructor(function(resolve, reject) { - handle(new Handler(onFulfilled, onRejected, resolve, reject)) - }) - } - - function handle(deferred) { - if (state === null) { - deferreds.push(deferred) - return - } - asap(function() { - var cb = state ? deferred.onFulfilled : deferred.onRejected - if (cb === null) { - (state ? deferred.resolve : deferred.reject)(value) - return - } - var ret - try { - ret = cb(value) - } - catch (e) { - deferred.reject(e) - return - } - deferred.resolve(ret) - }) - } - - function resolve(newValue) { - try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.') - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then - if (typeof then === 'function') { - doResolve(then.bind(newValue), resolve, reject) - return - } - } - state = true - value = newValue - finale() - } catch (e) { reject(e) } - } - - function reject(newValue) { - state = false - value = newValue - finale() - } - - function finale() { - for (var i = 0, len = deferreds.length; i < len; i++) - handle(deferreds[i]) - deferreds = null - } - - doResolve(fn, resolve, reject) -} - - -function Handler(onFulfilled, onRejected, resolve, reject){ - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null - this.onRejected = typeof onRejected === 'function' ? onRejected : null - this.resolve = resolve - this.reject = reject -} - -/** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ -function doResolve(fn, onFulfilled, onRejected) { - var done = false; - try { - fn(function (value) { - if (done) return - done = true - onFulfilled(value) - }, function (reason) { - if (done) return - done = true - onRejected(reason) - }) - } catch (ex) { - if (done) return - done = true - onRejected(ex) - } -} - -},{"asap":19}],16:[function(require,module,exports){ -'use strict'; - -var Promise = require('./core.js') -var asap = require('asap') - -module.exports = Promise -Promise.prototype.done = function (onFulfilled, onRejected) { - var self = arguments.length ? this.then.apply(this, arguments) : this - self.then(null, function (err) { - asap(function () { - throw err - }) - }) -} -},{"./core.js":15,"asap":19}],17:[function(require,module,exports){ -'use strict'; - -//This file contains the ES6 extensions to the core Promises/A+ API - -var Promise = require('./core.js') -var asap = require('asap') - -module.exports = Promise - -/* Static Functions */ - -function ValuePromise(value) { - this.then = function (onFulfilled) { - if (typeof onFulfilled !== 'function') return this - return new Promise(function (resolve, reject) { - asap(function () { - try { - resolve(onFulfilled(value)) - } catch (ex) { - reject(ex); - } - }) - }) - } -} -ValuePromise.prototype = Promise.prototype - -var TRUE = new ValuePromise(true) -var FALSE = new ValuePromise(false) -var NULL = new ValuePromise(null) -var UNDEFINED = new ValuePromise(undefined) -var ZERO = new ValuePromise(0) -var EMPTYSTRING = new ValuePromise('') - -Promise.resolve = function (value) { - if (value instanceof Promise) return value - - if (value === null) return NULL - if (value === undefined) return UNDEFINED - if (value === true) return TRUE - if (value === false) return FALSE - if (value === 0) return ZERO - if (value === '') return EMPTYSTRING - - if (typeof value === 'object' || typeof value === 'function') { - try { - var then = value.then - if (typeof then === 'function') { - return new Promise(then.bind(value)) - } - } catch (ex) { - return new Promise(function (resolve, reject) { - reject(ex) - }) - } - } - - return new ValuePromise(value) -} - -Promise.all = function (arr) { - var args = Array.prototype.slice.call(arr) - - return new Promise(function (resolve, reject) { - if (args.length === 0) return resolve([]) - var remaining = args.length - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then - if (typeof then === 'function') { - then.call(val, function (val) { res(i, val) }, reject) - return - } - } - args[i] = val - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex) - } - } - for (var i = 0; i < args.length; i++) { - res(i, args[i]) - } - }) -} - -Promise.reject = function (value) { - return new Promise(function (resolve, reject) { - reject(value); - }); -} - -Promise.race = function (values) { - return new Promise(function (resolve, reject) { - values.forEach(function(value){ - Promise.resolve(value).then(resolve, reject); - }) - }); -} - -/* Prototype Methods */ - -Promise.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -} - -},{"./core.js":15,"asap":19}],18:[function(require,module,exports){ -'use strict'; - -//This file contains then/promise specific extensions that are only useful for node.js interop - -var Promise = require('./core.js') -var asap = require('asap') - -module.exports = Promise - -/* Static Functions */ - -Promise.denodeify = function (fn, argumentCount) { - argumentCount = argumentCount || Infinity - return function () { - var self = this - var args = Array.prototype.slice.call(arguments) - return new Promise(function (resolve, reject) { - while (args.length && args.length > argumentCount) { - args.pop() - } - args.push(function (err, res) { - if (err) reject(err) - else resolve(res) - }) - var res = fn.apply(self, args) - if (res && (typeof res === 'object' || typeof res === 'function') && typeof res.then === 'function') { - resolve(res) - } - }) - } -} -Promise.nodeify = function (fn) { - return function () { - var args = Array.prototype.slice.call(arguments) - var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null - var ctx = this - try { - return fn.apply(this, arguments).nodeify(callback, ctx) - } catch (ex) { - if (callback === null || typeof callback == 'undefined') { - return new Promise(function (resolve, reject) { reject(ex) }) - } else { - asap(function () { - callback.call(ctx, ex) - }) - } - } - } -} - -Promise.prototype.nodeify = function (callback, ctx) { - if (typeof callback != 'function') return this - - this.then(function (value) { - asap(function () { - callback.call(ctx, null, value) - }) - }, function (err) { - asap(function () { - callback.call(ctx, err) - }) - }) -} - -},{"./core.js":15,"asap":19}],19:[function(require,module,exports){ -(function (process){ - -// Use the fastest possible means to execute a task in a future turn -// of the event loop. - -// linked list of tasks (single, with head node) -var head = {task: void 0, next: null}; -var tail = head; -var flushing = false; -var requestFlush = void 0; -var isNodeJS = false; - -function flush() { - /* jshint loopfunc: true */ - - while (head.next) { - head = head.next; - var task = head.task; - head.task = void 0; - var domain = head.domain; - - if (domain) { - head.domain = void 0; - domain.enter(); - } - - try { - task(); - - } catch (e) { - if (isNodeJS) { - // In node, uncaught exceptions are considered fatal errors. - // Re-throw them synchronously to interrupt flushing! - - // Ensure continuation if the uncaught exception is suppressed - // listening "uncaughtException" events (as domains does). - // Continue in next event to avoid tick recursion. - if (domain) { - domain.exit(); - } - setTimeout(flush, 0); - if (domain) { - domain.enter(); - } - - throw e; - - } else { - // In browsers, uncaught exceptions are not fatal. - // Re-throw them asynchronously to avoid slow-downs. - setTimeout(function() { - throw e; - }, 0); - } - } - - if (domain) { - domain.exit(); - } - } - - flushing = false; -} - -if (typeof process !== "undefined" && process.nextTick) { - // Node.js before 0.9. Note that some fake-Node environments, like the - // Mocha test runner, introduce a `process` global without a `nextTick`. - isNodeJS = true; - - requestFlush = function () { - process.nextTick(flush); - }; - -} else if (typeof setImmediate === "function") { - // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate - if (typeof window !== "undefined") { - requestFlush = setImmediate.bind(window, flush); - } else { - requestFlush = function () { - setImmediate(flush); - }; - } - -} else if (typeof MessageChannel !== "undefined") { - // modern browsers - // http://www.nonblocking.io/2011/06/windownexttick.html - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - requestFlush = function () { - channel.port2.postMessage(0); - }; - -} else { - // old browsers - requestFlush = function () { - setTimeout(flush, 0); - }; -} - -function asap(task) { - tail = tail.next = { - task: task, - domain: isNodeJS && process.domain, - next: null - }; - - if (!flushing) { - flushing = true; - requestFlush(); - } -}; - -module.exports = asap; - - -}).call(this,require('_process')) -},{"_process":48}],20:[function(require,module,exports){ -// jshint node: true - -var Promise = require('promise'); -var copyGraph = require('../graph.js').copyGraph; -var readonlyWrapper = require('../graph.js').readonlyWrapper; - -var MAX_AGE_REGEX = /max-age=([0-9]+)/; - -var BasicCore = function(iri, graph) { - if (!(this instanceof BasicCore)) return new BasicCore(iri, graph); - - var that = this; - - that.iri = iri; - that._graph = graph; - - var _editDepth = 0; - var _editableGraph; - - that.getState = function(forceRefresh) { - /** - Promises an RDF graph representing the current state of the core. - - Unless forceRefresh is true, that graph could be a cached version. - - stability: 3 - */ - return Promise.resolve(readonlyWrapper(graph)); - }; - - that.edit = function(editor, forceRefresh) { - /** - Promises to apply function 'editor' to the current state of the core, - and to return the resulting state. - - stability: 3 - */ - var p; - _editDepth += 1; - if (_editDepth === 1) { - //console.log('---', 'copying graph'); - p = copyGraph(graph) - .then(function(copiedGraph) { - _editableGraph = copiedGraph; - return editor(_editableGraph); - }) - .then(function() { - //console.log('---', 'commiting _editableGraph'); - return copyGraph(_editableGraph, graph); - }); - } else { - //console.log('---', 'reusing _editableGraph'); - p = Promise.resolve(_editableGraph) - .then( - editor - ); - } - p.then(function() { - _editDepth -= 1; - if (_editDepth === 0) _editableGraph = null; - }); - return p; - }; - - that.postGraph = function(graph) { - /** - Promises to process the posted graph. - - Not implemented in BasicCore. - - stability: 3 - */ - return Promise.reject("can't post graph to BasicCore"); - }; - - that.delete = function() { - /** - Promises to delete this core. - - Not implemented in BasicCore. - - stability: 3 - */ - return Promise.reject("can't delete BasicCore"); - }; - - Object.freeze(that); -}; - -exports.BasicCore = BasicCore; - - -},{"../graph.js":24,"promise":14}],21:[function(require,module,exports){ -// jshint node: true - -var _REGISTRY = []; - -exports.register = function(iriPrefix, subfactory) { - /** - Informs getCore to use subfactory to produce all cores starting with iriPrefix - - stability: 2 - */ - - // TODO sort prefixes in decreasing size order - // (to ensure priorities) - _REGISTRY.push({ - iriPrefix: iriPrefix, - subfactory: subfactory - }); -}; - -// TODO unregister - -exports.getCore = function(iri) { - /** - Return the appropriate Core for resource identified by iri - - stability: 3 - */ - - if (typeof iri === 'object') iri = iri['@id']; - var ret; - _REGISTRY.some(function(candidate) { - if(iri.split(candidate.iriPrefix, 1)[0] === '') { - ret = candidate.subfactory(iri); - return true; - } - }); - return ret; -}; - -// TODO remove this; this is for debug only -var BasicCore = require('./basic.js').BasicCore; -var graph = require('../graph.js').graph; -var makeIri = require('../rdfnode.js').iri; -exports.register("http://champin.net", function(iri) { - var g = graph(); - g.addTriple(makeIri(iri), - makeIri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), - makeIri('http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource') - ); - return new BasicCore(iri, g); -}); - - -var HttpCore = require('./http.js').HttpCore; -exports.register("http://", HttpCore); - - -},{"../graph.js":24,"../rdfnode.js":29,"./basic.js":20,"./http.js":22}],22:[function(require,module,exports){ -// jshint node: true - -var http = require('http'); -var https = require('https'); -var url = require('url'); -var Promise = require('promise'); - -var copyGraph = require('../graph.js').copyGraph; -var graph = require('../graph.js').graph; -var readonlyWrapper = require('../graph.js').readonlyWrapper; -var getParser = require('../parsers/factory.js').getParser; -var getSerializer = require('../serializers/factory.js').getSerializer; - -var MAX_AGE_REGEX = /max-age=([0-9]+)/; - -var HttpCore = function(iri) { - if (!(this instanceof HttpCore)) return new HttpCore(iri); - //console.log('---', 'new HttpCore', iri); - - var that = this; - - that.iri = iri; - var _parsedIri = url.parse(iri); - var _request; - if (_parsedIri.protocol === 'http:') { - _request = http.request; - if (_parsedIri.port === null) { - _parsedIri.port = 80; - } - } else if (_parsedIri.protocol === 'https:') { - _request = https.request; - if (_parsedIri.port === null) { - _parsedIri.port = 443; - } - } else { - throw "Unsupported protocol: " + this._parsedIri.protocol; - } - var _graph; - var _etag; - var _validUntil; - var _editDepth = 0; - var _editableGraph = null; - - that.getState = function(forceRefresh) { - return new Promise(function(resolve, reject) { - if (!forceRefresh && _validUntil && Date.now() <= _validUntil) { - resolve(_graph); - return; - } - var options = { - hostname: _parsedIri.hostname, - port: _parsedIri.port, - path: _parsedIri.path, - method: 'GET', - headers: { - // TODO generate accept header based on registered parsers? - } - }; - if (!forceRefresh && _etag) { - options.headers['if-none-match'] = _etag; - } - var req = _request(options, function(res) { - if (res.statusCode === 200 || res.statusCode === 304) { - _etag = res.headers.etag; - var match = MAX_AGE_REGEX.exec(res.headers['cache-control']); - _validUntil = match ? - (Date.now() + Number(match[1])*1000) : undefined; - if (res.statusCode === 304) { - resolve(_graph); - return; - } - _graph = graph(); - var p = getParser({ - contentType:'application/ld+json', - graph: _graph - }); - //res.setEncoding('utf8'); - res.on('data', function (chunk) { - p.addChunk(chunk); - }); - res.on('end', function() { - p.finalize().then(function() { - resolve(_graph); - }) - }); - } else { - reject("Unsupported statusCode " + res.statusCode); - // TODO handle redirections correctly? - } - }); - - req.on('error', function(err) { - reject(err); - }); - req.end(); - }).then(function(theGraph) { - return readonlyWrapper(theGraph); - }) - ; - }; - - that.edit = function(editor, forceRefresh) { - var p; - _editDepth += 1; - if (_editDepth === 1) { - //console.log('---', 'copying graph'); - var req, reqProm, serialize; - p = that.getState(forceRefresh) - .then(function() { - return copyGraph(_graph); - }) - .then(function(copiedGraph) { - _editableGraph = copiedGraph; - return editor(_editableGraph); - }) - .then(function() { - //console.log('---', 'commiting _editableGraph'); - var ctype = 'application/ld+json'; // TODO decide based on server? - serialize = getSerializer({ - contentType: ctype, - graph: _editableGraph - }); - var options = { - hostname: _parsedIri.hostname, - port: _parsedIri.port, - path: _parsedIri.path, - method: 'PUT', - headers: { - 'content-type': ctype - } - }; - if (_etag) { - options.headers['if-match'] = _etag; - } - reqProm = new Promise(function(resolve, reject) { - req = _request(options, function(res) { - resolve(res); - }); - req.on('error', function(err) { - reject(err); - }); - }); - }) - .then(function() { - return serialize(function(chunk) { req.write(chunk); }); - }) - .then(function() { - req.end(); - return reqProm; - }) - .then(function(res) { - return new Promise(function(resolve, reject) { - if (res.statusCode / 100 === 2) { - _etag = res.headers.etag; - var match = MAX_AGE_REGEX.exec(res.headers['cache-control']); - _validUntil = match ? - (Date.now() + Number(match[1])*1000) : undefined; - _graph = graph(); - var p = getParser({ - contentType:'application/ld+json', - graph: _graph - }); - res.setEncoding('utf8'); - res.on('data', function (chunk) { - p.addChunk(chunk); - }); - res.on('end', function() { - p.finalize().then(resolve(readonlyWrapper(_graph))); - }); - } else { - reject("Unsupported statusCode " + res.statusCode); - // TODO handle redirections?? - } - }); - }) - ; - } else { - //console.log('---', 'reusing _editableGraph'); - p = Promise.resolve(_editableGraph) - .then( - editor - ); - } - p.then(function() { - _editDepth -= 1; - if (_editDepth === 0) _editableGraph = null; - }); - return p; - }; - - that.postGraph = function(graph) { - /** - Promises to process the posted graph. - - Not implemented in BasicCore. - - stability: 3 - */ - return Promise.reject("can't post graph to BasicCore"); - }; - - that.delete = function() { - /** - Promises to delete this core. - - Not implemented in BasicCore. - - stability: 3 - */ - return Promise.reject("can't delete BasicCore"); - }; - - Object.freeze(that); -}; - -exports.HttpCore = HttpCore; - -},{"../graph.js":24,"../parsers/factory.js":26,"../serializers/factory.js":30,"http":40,"https":44,"promise":14,"url":66}],23:[function(require,module,exports){ -// jshint node: true - -var namespace = require('../rdfnode.js').namespace; - -var HYDRA = namespace('http://www.w3.org/ns/hydra/core#'); - -var HydraCore = function(core, hydraspec, restcontext) { - /** - A Core implementing a given Hydra specification. - - core: the underlying core object (actually implementing the operations) - hydraspec: an RDF graph containing the Hydra specification - restcontext: an object describing the REST context of this resource - (useful to locate which part(s) of the Hydra specification apply to it) - - stability: 1 - */ - - that.getState = function(forceRefresh) { - /** - Promises an RDF graph representing the current state of the core. - - Unless forceRefresh is true, that graph could be a cached version. - - stability: 3 - */ - // TODO, among other things: - // - check that GET is supported - // - remove write-only properties if any - }; - - that.edit = function(editor) { - /** - Promises to apply function 'editor' to the current state of the core, - and to return the resulting state. - - stability: 3 - */ - // TODO, among other things: - // - check if PUT is supported - // - check that the edited graph does not violates any constraint - }; - - that.postGraph = function(graph) { - /** - Promises to process the posted graph. - - Not implemented in BasicCore. - - stability: 3 - */ - // TODO, among other things: - // - check if POST is supported - // - check that the posted graph does not violates any constraint - }; - - that.delete = function() { - /** - Promises to delete this core. - - Not implemented in BasicCore. - - stability: 3 - */ - // TODO, among other things: - // - check if DELETE is supported - }; - - Object.freeze(that); -}; - -},{"../rdfnode.js":29}],24:[function(require,module,exports){ -// jshint node: true - -var Promise = require('promise'); -var assert = require('assert'); - -var rdfnode = require('./rdfnode.js'); -var canonicalize = rdfnode.canonicalize; -var sameNode = rdfnode.sameNode; - - -function decanonicalize(n) { - var id = n['@id']; - assert(id !== undefined); - return id; -} - -function addToIndex(index, key1, key2, val) { - key1 = decanonicalize(key1); - var subindex1 = index[key1]; - if (subindex1 === undefined) { - subindex1 = index[key1] = {}; - } - key2 = decanonicalize(key2); - var subindex2 = subindex1[key2]; - if (subindex2 === undefined) { - subindex2 = subindex1[key2] = {}; - } - var key3 = val['@id'] || val['@value']; - var vals = subindex2[key3]; - if (vals === undefined) { - vals = subindex2[key3] = []; - } - var found = false; - vals.forEach(function (otherval) { - if(sameNode(val, otherval)) found=true; - }); - if (!found) { - vals.push(val); - } -} - -function removeFromIndex(index, key1, key2, val) { - key1 = decanonicalize(key1); - var subindex1 = index[key1]; - if (subindex1 === undefined) { - return; - } - key2 = decanonicalize(key2); - var subindex2 = subindex1[key2]; - if (subindex2 === undefined) { - return; - } - var key3 = val['@id'] || val['@value']; - var vals = subindex2[key3]; - if (vals === undefined) { - return; - } - var newvals = []; - vals.forEach(function (otherval) { - if(!sameNode(val, otherval)) newvals.push(otherval); - }); - if (newvals.length) { - subindex2[key3] = newvals; - } else { - delete subindex2[key3]; - if (!Object.keys(subindex2).length) { - delete subindex1[key2]; - if (!Object.keys(subindex1).length) { - delete index[key1]; - } - } - } -} - -function forEachObject(s, p, objects, o, handler, promises) { - //console.log("---", "fEO", s, p, objects, o); - var key; - if (o !== null) { - key = o['@id'] || o['@value']; - var candidates = objects[key]; - if (candidates.length) { - candidates.forEach(function(c) { - if (sameNode(o, c)) { - promises.push(Promise.resolve(handler(s, p, c))); - } - }); - } - } else { - for(key in objects) { - objects[key].forEach(function(c) { - promises.push(Promise.resolve(handler(s, p, c))); - }); - } - } -} - -function forEachPredicate(s, predicates, p, o, handler, promises) { - //console.log("---", "fEP", s, predicates, p, o); - var key; - if (p !== null) { - key = decanonicalize(p); - var objects = predicates[key]; - if (objects) forEachObject(s, p, objects, o, handler, promises); - } else { - for (key in predicates) { - forEachObject(s, { '@id': key }, predicates[key], o, handler, promises); - } - } -} - - -exports.graph = function() { - var that = {}; - var subjects = {}; - that._subjects = subjects; // for easier debug only - - that.addTriple = function (s, p, o) { - /** - Promises to add triple (s, p, o) to that graph. - - The promise won't fail if the triple is already there. - - stability: 2 - (return value, if any, is stil to be decided) - */ - return new Promise(function(resolve, reject) { - resolve( - addToIndex(subjects, s, p, canonicalize(o)) - ); - }); - }; - - that.removeTriple = function (s, p, o) { - /** - Promises to remove triple (s, p, o) from that graph. - - The promise won't fail if the triple is not there. - - stability: 2 - (return value, if any, is stil to be decided) - */ - return new Promise(function(resolve, reject) { - resolve( - removeFromIndex(subjects, s, p, canonicalize(o)) - ); - }); - }; - - that.containsTriple = function (s, p, o) { - /** - Promises a boolean indicating whether triple (s, p, o) is in that graph. - - stability: 3 - */ - var found = false; - var prom = that.forEachTriple(s, p, o, function() { - found = true; - }).then( - function() { - return found; - } - ); - return prom; - }; - - that.forEachTriple = function (s, p, o, handler) { - /** - Promises to call 'handler' on every triple matching (s, p, o). - - stability: 1 - yet to decide if handlers must be ran in parallel or in sequence. - parallel seems more general, but sequence is usefull - 1/ to allows to stop early if one fails... - 2/ for serializers - may be we need both semantics? - or may be we must return an array of promises, - and let the user decide (with Promise.all or Promise.any) ? - */ - //console.log('---', 'fET', s, p, o); - if (o !== null) o = canonicalize(o); - var key; - var promises = []; - if (s !== null) { - key = decanonicalize(s); - var predicates = subjects[key]; - if (predicates) forEachPredicate(s, predicates, p, o, handler, promises); - } else { - for (key in subjects) { - forEachPredicate({'@id': key}, subjects[key], p, o, handler, promises); - } - } - return Promise.all(promises); - }; - - that.countTriples = function () { - /** - Promises to provide the number of triples in that graph. - - stability: 3 - */ - var count = 0; - return that.forEachTriple(null, null, null, function() { count += 1; }) - .then(function() { - return count; - }); - }; - - return that; -}; - -exports.copyGraph = function(g1, g2) { - return new Promise(function(resolve, reject) { - if (g2 === undefined) { - g2 = exports.graph(); - } - g1.forEachTriple(null, null, null, g2.addTriple).then( - function () { resolve(g2); }, - reject - ); - }); -}; - - -exports.readonlyWrapper = function(g) { - // TODO implement this correctly - return g; -}; - -// TODO alternative to readonlyWrapper: cowWrapper (Copy On Write) ? - -},{"./rdfnode.js":29,"assert":34,"promise":14}],25:[function(require,module,exports){ -// jshint node: true - -var assert = require('assert'); -var Promise = require('promise'); - -var Parser = function(graph) { - "use strict"; - if (!(this instanceof Parser)) { - return new Parser(graph); - } - - var that = this; - var _txt = ""; - that.addChunk = function(chunk) { - _txt += chunk; - }; - that.finalize = function() { - var json = JSON.parse(_txt); - assert(json.length !== undefined); - var promises = []; - json.forEach(function(triple) { - if (triple['@id'] === undefined) return; - var s, p, o; - s = { '@id': triple['@id'] }; - for (var k in triple) { - if (k !== '@id') { - p = { '@id': k }; - o = triple[k]; - if (o['@language'] !== undefined) { - o['@type'] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"; - } - } - } - if (!(p && o)) { - throw "invalid triple structure " + triple; - } - promises.push(graph.addTriple(s, p, o)); - }); - return Promise.all(promises) - .then(function() { return graph; }); - }; -}; - -exports.Parser = Parser; - -require('./factory.js').register({ - contentType: 'application/debug+json', - parserMaker: Parser -}); - -},{"./factory.js":26,"assert":34,"promise":14}],26:[function(require,module,exports){ -// jshint node: true - -var _REGISTRY = {}; - -exports.register = function(args) { - _REGISTRY[args.contentType] = args.parserMaker; -}; - -exports.getParser = function(args) { - var parserMaker = _REGISTRY[args.contentType]; - if (!parserMaker) { - throw "Could not find parser for " + JSON.stringify(args); - } - return parserMaker(args.graph); -}; - -// TODO add other parameters to registry: -// - domain name -// - rdf type -// - priority - -},{}],27:[function(require,module,exports){ -"use strict"; - -var jsonld = require('jsonld'); -var Promise = require('promise'); -var graph = require('../graph.js').graph; -var iri = require('../rdfnode.js').iri; - -var Parser = function(graph) { - if (!(this instanceof Parser)) { - return new Parser(graph); - } - - var that = this; - var _txt = ""; - that.addChunk = function(chunk) { - _txt += chunk; - }; - - that.finalize = function() { - return new Promise(function (resolve, reject) { - var jsonLdPro = new jsonld.JsonLdProcessor(); - - _txt = JSON.parse(_txt); - - jsonLdPro.toRDF(_txt).then(function (dataset) { - var resultArr = dataset["@default"]; - resultArr.forEach(function (triple) { - if ( ((/string/).test(triple.object.datatype)) && - ((/literal/).test(triple.object.type)) ) { - // TODO unsafe checking ? - - // the object of the triple is a literal of type string, - // we use the automatic canonicalisation of graph.js: - graph.addTriple( - iri(triple.subject.value), - iri(triple.predicate.value), - triple.object.value); - // TODO explicitly using canonicalize ? - - } else { - graph.addTriple( - iri(triple.subject.value), - iri(triple.predicate.value), - iri(triple.object.value)); - } // TODO maybe a condition is missing here - }); - if (graph) { - resolve(graph); - } else { - reject(graph); - } - }, function (err) { - console.log(err); - reject(graph); - }); - }); - }; -}; - -exports.Parser = Parser; - -require('./factory.js').register({ - contentType: 'application/ld+json', - parserMaker: Parser -}); - -},{"../graph.js":24,"../rdfnode.js":29,"./factory.js":26,"jsonld":3,"promise":14}],28:[function(require,module,exports){ -"use strict"; - -var N3 = require('n3'); -var Promise = require('promise'); -var graph = require('../graph.js').graph; -var iri = require('../rdfnode.js').iri; - -/** - * Returns a Promise that is able to serve a graph representation - * @param ntriples - */ -exports.toGraph = function (ntriples) { - var aPromise = new Promise(function (resolve, reject) { - var parser = N3.Parser(), - g = graph(); - parser.parse(ntriples, function (error, triple) { - if (triple) { - g.addTriple(iri(triple.subject), - iri(triple.predicate), triple.object); // on ajoute un à un les triplets - } else { - // parsing is done, we can continue - if (g) { - resolve(g); - } else { - reject(new Error("g is null")); - } - } - if (error) { - reject(new Error("It broke")); - } - }); - }); - return aPromise; -}; - - -},{"../graph.js":24,"../rdfnode.js":29,"n3":6,"promise":14}],29:[function(require,module,exports){ -// jshint node: true -var assert = require('assert'); - -var RDF_LANGSTRING = "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"; -var XSD_BOOLEAN = "http://www.w3.org/2001/XMLSchema#boolean"; -var XSD_DOUBLE = "http://www.w3.org/2001/XMLSchema#double"; -var XSD_INTEGER = "http://www.w3.org/2001/XMLSchema#integer"; -var XSD_STRING = "http://www.w3.org/2001/XMLSchema#string"; - -exports.iri = function(iristr) { - return { '@id': iristr }; -}; -var iri = exports.iri; - -exports.namespace = function(iristr) { - if (typeof iristr === 'object') { // also accept iri nodes - iristr = iri['@id']; - } - return function (suffix) { - return iri(iristr + suffix); - }; -}; - -exports.bnode = function(bnodeid) { - if (bnodeid === undefined) { - // TODO coin a fresh bnodeid - throw "not implemented yet"; - } - return { '@id': '_:'+bnodeid }; -}; - -exports.langstring = function(value, language) { - return { - '@value': value, - '@language': language, - '@type': RDF_LANGSTRING - }; -}; - -exports.canonicalize = function(n) { - var typeofn = typeof n; - if(typeofn === 'object') { - // optimistic optimization: we do not check for @id or @value - return n; - // TODO should we be more strict ? - } else if (typeofn === 'string') { - return { "@value": n, "@type": XSD_STRING }; - } else if (typeofn === 'boolean') { - return { "@value": String(n), "@type": XSD_BOOLEAN }; - } else if (typeofn === 'number') { - throw "TODO: implement int vs. float distinction"; - } else { - throw "unrecognized node"; - } - // TODO for strings (if typeofn is object or string), - // should we still include @type xsd:string? -}; - -exports.toNT = function(n) { - assert(typeof n === 'object'); // should be canonicalized - id = n['@id']; - if (id !== undefined) { - var id = n['@id']; - if (id[0] === '_') { - ret = id; - } else { - ret = '<' + id + '>'; - } - } else { - var value = n['@value']; - assert(value !== undefined); - // TODO JSON escaping may not be strictly equivalent to NT escaping - var ret = JSON.stringify(value); - var datatype = n['@type']; - if (datatype === XSD_STRING) { - // LEAVE DATATYPE IMPLICIT - } else if (datatype === RDF_LANGSTRING) { - var language = n['@language']; - if (language !== undefined) { - ret += '@' + language; - } - } else { - ret += '^^<' + datatype + '>'; - } - } - return ret; -}; - -exports.sameNode = function(n1, n2) { - assert(typeof n1 === 'object'); // must be in canonical form - assert(typeof n2 === 'object'); // must be in canonical form - return ( - n1['@id'] === n2['@id'] && - n1['@value'] === n2['@value'] && - n1['@type'] === n2['@type'] && - n1['@language'] === n2['@language'] - ); -}; - - -},{"assert":34}],30:[function(require,module,exports){ -// jshint node: true - -var _REGISTRY = {}; - -exports.register = function(args) { - _REGISTRY[args.contentType] = args.serializer; -}; - -exports.getSerializer = function(args) { - var serializer = _REGISTRY[args.contentType]; - if (!serializer) { - throw "Could not find serializer for " + JSON.stringify(args); - } - return function(callback) { - return serializer(args.graph, callback); - }; -}; - -// TODO add other parameters to registry: -// - domain name -// - rdf type -// - priority - -},{}],31:[function(require,module,exports){ -// jshint node: true -var Promise = require('promise'); - -var jsonld = function(graph, callback) { - return new Promise(function(resolve, reject) { - callback('['); - resolve(); - }) - .then(function() { - return graph.forEachTriple(null, null, null, function(s, p, o) { - if (o['@language']) { - // JSON-LD does not support both @type and @language - o = { - '@value': o['@value'], - '@language': o['@language'] - }; - } - var triple = { '@id': s['@id'] }; - triple[p['@id']] = o; - callback(JSON.stringify(triple) + ","); - }); - }) - .then(function() { - callback('{}]'); - }); -}; -exports.jsonld = jsonld; - -var register = require('./factory.js').register; - -register({ - contentType: 'application/debug+json', - serializer: jsonld -}); -register({ - contentType: 'application/ld+json', - serializer: jsonld -}); -register({ - contentType: 'application/json', - serializer: jsonld -}); - -},{"./factory.js":30,"promise":14}],32:[function(require,module,exports){ -// jshint node: true -var toNT = require('../rdfnode.js').toNT; -var Promise = require('promise'); - -var nt = function(graph, callback) { - return graph.forEachTriple(null, null, null, function(s, p, o) { - callback(toNT(s) + " " + toNT(p) + " " + toNT(o) + "."); - }); -}; -exports.nt = nt; - -var register = require('./factory.js').register; - -register({ - contentType: 'application/n-triples', - serializer: nt -}); -register({ - contentType: 'text/plain', - serializer: nt -}); - -},{"../rdfnode.js":29,"./factory.js":30,"promise":14}],33:[function(require,module,exports){ - -},{}],34:[function(require,module,exports){ -// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 -// -// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! -// -// Originally from narwhal.js (http://narwhaljs.org) -// Copyright (c) 2009 Thomas Robinson <280north.com> -// -// 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: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// when used in node, this will actually load the util module we depend on -// versus loading the builtin util module as happens otherwise -// this is a bug in node module loading as far as I am concerned -var util = require('util/'); - -var pSlice = Array.prototype.slice; -var hasOwn = Object.prototype.hasOwnProperty; - -// 1. The assert module provides functions that throw -// AssertionError's when particular conditions are not met. The -// assert module must conform to the following interface. - -var assert = module.exports = ok; - -// 2. The AssertionError is defined in assert. -// new assert.AssertionError({ message: message, -// actual: actual, -// expected: expected }) - -assert.AssertionError = function AssertionError(options) { - this.name = 'AssertionError'; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - if (options.message) { - this.message = options.message; - this.generatedMessage = false; - } else { - this.message = getMessage(this); - this.generatedMessage = true; - } - var stackStartFunction = options.stackStartFunction || fail; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, stackStartFunction); - } - else { - // non v8 browsers so we can have a stacktrace - var err = new Error(); - if (err.stack) { - var out = err.stack; - - // try to strip useless frames - var fn_name = stackStartFunction.name; - var idx = out.indexOf('\n' + fn_name); - if (idx >= 0) { - // once we have located the function frame - // we need to strip out everything before it (and its line) - var next_line = out.indexOf('\n', idx + 1); - out = out.substring(next_line + 1); - } - - this.stack = out; - } - } -}; - -// assert.AssertionError instanceof Error -util.inherits(assert.AssertionError, Error); - -function replacer(key, value) { - if (util.isUndefined(value)) { - return '' + value; - } - if (util.isNumber(value) && !isFinite(value)) { - return value.toString(); - } - if (util.isFunction(value) || util.isRegExp(value)) { - return value.toString(); - } - return value; -} - -function truncate(s, n) { - if (util.isString(s)) { - return s.length < n ? s : s.slice(0, n); - } else { - return s; - } -} - -function getMessage(self) { - return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + - self.operator + ' ' + - truncate(JSON.stringify(self.expected, replacer), 128); -} - -// At present only the three keys mentioned above are used and -// understood by the spec. Implementations or sub modules can pass -// other keys to the AssertionError's constructor - they will be -// ignored. - -// 3. All of the following functions must throw an AssertionError -// when a corresponding condition is not met, with a message that -// may be undefined if not provided. All assertion methods provide -// both the actual and expected values to the assertion error for -// display purposes. - -function fail(actual, expected, message, operator, stackStartFunction) { - throw new assert.AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); -} - -// EXTENSION! allows for well behaved errors defined elsewhere. -assert.fail = fail; - -// 4. Pure assertion tests whether a value is truthy, as determined -// by !!guard. -// assert.ok(guard, message_opt); -// This statement is equivalent to assert.equal(true, !!guard, -// message_opt);. To test strictly for the value true, use -// assert.strictEqual(true, guard, message_opt);. - -function ok(value, message) { - if (!value) fail(value, true, message, '==', assert.ok); -} -assert.ok = ok; - -// 5. The equality assertion tests shallow, coercive equality with -// ==. -// assert.equal(actual, expected, message_opt); - -assert.equal = function equal(actual, expected, message) { - if (actual != expected) fail(actual, expected, message, '==', assert.equal); -}; - -// 6. The non-equality assertion tests for whether two objects are not equal -// with != assert.notEqual(actual, expected, message_opt); - -assert.notEqual = function notEqual(actual, expected, message) { - if (actual == expected) { - fail(actual, expected, message, '!=', assert.notEqual); - } -}; - -// 7. The equivalence assertion tests a deep equality relation. -// assert.deepEqual(actual, expected, message_opt); - -assert.deepEqual = function deepEqual(actual, expected, message) { - if (!_deepEqual(actual, expected)) { - fail(actual, expected, message, 'deepEqual', assert.deepEqual); - } -}; - -function _deepEqual(actual, expected) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - - } else if (util.isBuffer(actual) && util.isBuffer(expected)) { - if (actual.length != expected.length) return false; - - for (var i = 0; i < actual.length; i++) { - if (actual[i] !== expected[i]) return false; - } - - return true; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (util.isDate(actual) && util.isDate(expected)) { - return actual.getTime() === expected.getTime(); - - // 7.3 If the expected value is a RegExp object, the actual value is - // equivalent if it is also a RegExp object with the same source and - // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). - } else if (util.isRegExp(actual) && util.isRegExp(expected)) { - return actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase; - - // 7.4. Other pairs that do not both pass typeof value == 'object', - // equivalence is determined by ==. - } else if (!util.isObject(actual) && !util.isObject(expected)) { - return actual == expected; - - // 7.5 For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical 'prototype' property. Note: this - // accounts for both named and indexed properties on Arrays. - } else { - return objEquiv(actual, expected); - } -} - -function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; -} - -function objEquiv(a, b) { - if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) - return false; - // an identical 'prototype' property. - if (a.prototype !== b.prototype) return false; - // if one is a primitive, the other must be same - if (util.isPrimitive(a) || util.isPrimitive(b)) { - return a === b; - } - var aIsArgs = isArguments(a), - bIsArgs = isArguments(b); - if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) - return false; - if (aIsArgs) { - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a, b); - } - var ka = objectKeys(a), - kb = objectKeys(b), - key, i; - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length != kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] != kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!_deepEqual(a[key], b[key])) return false; - } - return true; -} - -// 8. The non-equivalence assertion tests for any deep inequality. -// assert.notDeepEqual(actual, expected, message_opt); - -assert.notDeepEqual = function notDeepEqual(actual, expected, message) { - if (_deepEqual(actual, expected)) { - fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); - } -}; - -// 9. The strict equality assertion tests strict equality, as determined by ===. -// assert.strictEqual(actual, expected, message_opt); - -assert.strictEqual = function strictEqual(actual, expected, message) { - if (actual !== expected) { - fail(actual, expected, message, '===', assert.strictEqual); - } -}; - -// 10. The strict non-equality assertion tests for strict inequality, as -// determined by !==. assert.notStrictEqual(actual, expected, message_opt); - -assert.notStrictEqual = function notStrictEqual(actual, expected, message) { - if (actual === expected) { - fail(actual, expected, message, '!==', assert.notStrictEqual); - } -}; - -function expectedException(actual, expected) { - if (!actual || !expected) { - return false; - } - - if (Object.prototype.toString.call(expected) == '[object RegExp]') { - return expected.test(actual); - } else if (actual instanceof expected) { - return true; - } else if (expected.call({}, actual) === true) { - return true; - } - - return false; -} - -function _throws(shouldThrow, block, expected, message) { - var actual; - - if (util.isString(expected)) { - message = expected; - expected = null; - } - - try { - block(); - } catch (e) { - actual = e; - } - - message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + - (message ? ' ' + message : '.'); - - if (shouldThrow && !actual) { - fail(actual, expected, 'Missing expected exception' + message); - } - - if (!shouldThrow && expectedException(actual, expected)) { - fail(actual, expected, 'Got unwanted exception' + message); - } - - if ((shouldThrow && actual && expected && - !expectedException(actual, expected)) || (!shouldThrow && actual)) { - throw actual; - } -} - -// 11. Expected to throw an error: -// assert.throws(block, Error_opt, message_opt); - -assert.throws = function(block, /*optional*/error, /*optional*/message) { - _throws.apply(this, [true].concat(pSlice.call(arguments))); -}; - -// EXTENSION! This is annoying to write outside this module. -assert.doesNotThrow = function(block, /*optional*/message) { - _throws.apply(this, [false].concat(pSlice.call(arguments))); -}; - -assert.ifError = function(err) { if (err) {throw err;}}; - -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - if (hasOwn.call(obj, key)) keys.push(key); - } - return keys; -}; - -},{"util/":68}],35:[function(require,module,exports){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('is-array') - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 // not used by this implementation - -var kMaxLength = 0x3fffffff -var rootParent = {} - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Note: - * - * - Implementation must support adding new properties to `Uint8Array` instances. - * Firefox 4-29 lacked support, fixed in Firefox 30+. - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - * - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will - * get the Object implementation, which is slower but will work correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = (function () { - try { - var buf = new ArrayBuffer(0) - var arr = new Uint8Array(buf) - arr.foo = function () { return 42 } - return 42 === arr.foo() && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -})() - -/** - * Class: Buffer - * ============= - * - * The Buffer constructor returns instances of `Uint8Array` that are augmented - * with function properties for all the node `Buffer` API functions. We use - * `Uint8Array` so that square bracket notation works as expected -- it returns - * a single octet. - * - * By augmenting the instances, we can avoid modifying the `Uint8Array` - * prototype. - */ -function Buffer (subject, encoding, noZero) { - if (!(this instanceof Buffer)) - return new Buffer(subject, encoding, noZero) - - var type = typeof subject - - // Find the length - var length - if (type === 'number') - length = subject > 0 ? subject >>> 0 : 0 - else if (type === 'string') { - length = Buffer.byteLength(subject, encoding) - } else if (type === 'object' && subject !== null) { // assume object is array-like - if (subject.type === 'Buffer' && isArray(subject.data)) - subject = subject.data - length = +subject.length > 0 ? Math.floor(+subject.length) : 0 - } else - throw new TypeError('must start with number, buffer, array or string') - - if (length > kMaxLength) - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength.toString(16) + ' bytes') - - var buf - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Preferred: Return an augmented `Uint8Array` instance for best performance - buf = Buffer._augment(new Uint8Array(length)) - } else { - // Fallback: Return THIS instance of Buffer (created by `new`) - buf = this - buf.length = length - buf._isBuffer = true - } - - var i - if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { - // Speed optimization -- use set if we're copying from a typed array - buf._set(subject) - } else if (isArrayish(subject)) { - // Treat array-ish objects as a byte array - if (Buffer.isBuffer(subject)) { - for (i = 0; i < length; i++) - buf[i] = subject.readUInt8(i) - } else { - for (i = 0; i < length; i++) - buf[i] = ((subject[i] % 256) + 256) % 256 - } - } else if (type === 'string') { - buf.write(subject, 0, encoding) - } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { - for (i = 0; i < length; i++) { - buf[i] = 0 - } - } - - if (length > 0 && length <= Buffer.poolSize) - buf.parent = rootParent - - return buf -} - -function SlowBuffer(subject, encoding, noZero) { - if (!(this instanceof SlowBuffer)) - return new SlowBuffer(subject, encoding, noZero) - - var buf = new Buffer(subject, encoding, noZero) - delete buf.parent - return buf -} - -Buffer.isBuffer = function (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.compare = function (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) - throw new TypeError('Arguments must be Buffers') - - var x = a.length - var y = b.length - for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} - if (i !== len) { - x = a[i] - y = b[i] - } - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'binary': - case 'base64': - case 'raw': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function (list, totalLength) { - if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') - - if (list.length === 0) { - return new Buffer(0) - } else if (list.length === 1) { - return list[0] - } - - var i - if (totalLength === undefined) { - totalLength = 0 - for (i = 0; i < list.length; i++) { - totalLength += list[i].length - } - } - - var buf = new Buffer(totalLength) - var pos = 0 - for (i = 0; i < list.length; i++) { - var item = list[i] - item.copy(buf, pos) - pos += item.length - } - return buf -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str + '' - switch (encoding || 'utf8') { - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - case 'hex': - ret = str.length >>> 1 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'base64': - ret = base64ToBytes(str).length - break - default: - ret = str.length - } - return ret -} - -// pre-set for values that may exist in the future -Buffer.prototype.length = undefined -Buffer.prototype.parent = undefined - -// toString(encoding, start=0, end=buffer.length) -Buffer.prototype.toString = function (encoding, start, end) { - var loweredCase = false - - start = start >>> 0 - end = end === undefined || end === Infinity ? this.length : end >>> 0 - - if (!encoding) encoding = 'utf8' - if (start < 0) start = 0 - if (end > this.length) end = this.length - if (end <= start) return '' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'binary': - return binarySlice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) - throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.equals = function (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') - if (this.length > max) - str += ' ... ' - } - return '' -} - -Buffer.prototype.compare = function (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - return Buffer.compare(this, b) -} - -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new Error('Invalid hex string') - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; i++) { - var byte = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(byte)) throw new Error('Invalid hex string') - buf[offset + i] = byte - } - return i -} - -function utf8Write (buf, string, offset, length) { - var charsWritten = blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) - return charsWritten -} - -function asciiWrite (buf, string, offset, length) { - var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) - return charsWritten -} - -function binaryWrite (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} - -function base64Write (buf, string, offset, length) { - var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) - return charsWritten -} - -function utf16leWrite (buf, string, offset, length) { - var charsWritten = blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length, 2) - return charsWritten -} - -Buffer.prototype.write = function (string, offset, length, encoding) { - // Support both (string, offset, length, encoding) - // and the legacy (string, encoding, offset, length) - if (isFinite(offset)) { - if (!isFinite(length)) { - encoding = length - length = undefined - } - } else { // legacy - var swap = encoding - encoding = offset - offset = length - length = swap - } - - offset = Number(offset) || 0 - - if (length < 0 || offset < 0 || offset > this.length) - throw new RangeError('attempt to write outside buffer bounds'); - - var remaining = this.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - encoding = String(encoding || 'utf8').toLowerCase() - - var ret - switch (encoding) { - case 'hex': - ret = hexWrite(this, string, offset, length) - break - case 'utf8': - case 'utf-8': - ret = utf8Write(this, string, offset, length) - break - case 'ascii': - ret = asciiWrite(this, string, offset, length) - break - case 'binary': - ret = binaryWrite(this, string, offset, length) - break - case 'base64': - ret = base64Write(this, string, offset, length) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = utf16leWrite(this, string, offset, length) - break - default: - throw new TypeError('Unknown encoding: ' + encoding) - } - return ret -} - -Buffer.prototype.toJSON = function () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - var res = '' - var tmp = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - if (buf[i] <= 0x7F) { - res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) - tmp = '' - } else { - tmp += '%' + buf[i].toString(16) - } - } - - return res + decodeUtf8Char(tmp) -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} - -function binarySlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function hexSlice (buf, start, end) { - var len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - var out = '' - for (var i = start; i < end; i++) { - out += toHex(buf[i]) - } - return out -} - -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) - } - return res -} - -Buffer.prototype.slice = function (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len; - if (start < 0) - start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) - end = 0 - } else if (end > len) { - end = len - } - - if (end < start) - end = start - - var newBuf - if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = Buffer._augment(this.subarray(start, end)) - } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined, true) - for (var i = 0; i < sliceLen; i++) { - newBuf[i] = this[i + start] - } - } - - if (newBuf.length) - newBuf.parent = this.parent || this - - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) - throw new RangeError('offset is not uint') - if (offset + ext > length) - throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUIntLE = function (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) - val += this[offset + i] * mul - - return val -} - -Buffer.prototype.readUIntBE = function (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkOffset(offset, byteLength, this.length) - - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) - val += this[offset + --byteLength] * mul; - - return val -} - -Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUInt16LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUInt16BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUInt32LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readIntLE = function (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) - val += this[offset + i] * mul - mul *= 0x80 - - if (val >= mul) - val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkOffset(offset, byteLength, this.length) - - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) - val += this[offset + --i] * mul - mul *= 0x80 - - if (val >= mul) - val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) - return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readFloatLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') - if (value > max || value < min) throw new RangeError('value is out of bounds') - if (offset + ext > buf.length) throw new RangeError('index out of range') -} - -Buffer.prototype.writeUIntLE = function (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) - - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) - this[offset + i] = (value / mul) >>> 0 & 0xFF - - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) - checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) - - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) - this[offset + i] = (value / mul) >>> 0 & 0xFF - - return offset + byteLength -} - -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = value - return offset + 1 -} - -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - -Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - } else objectWriteUInt16(this, value, offset, true) - return offset + 2 -} - -Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = value - } else objectWriteUInt16(this, value, offset, false) - return offset + 2 -} - -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - -Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = value - } else objectWriteUInt32(this, value, offset, true) - return offset + 4 -} - -Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = value - } else objectWriteUInt32(this, value, offset, false) - return offset + 4 -} - -Buffer.prototype.writeIntLE = function (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkInt(this, - value, - offset, - byteLength, - Math.pow(2, 8 * byteLength - 1) - 1, - -Math.pow(2, 8 * byteLength - 1)) - } - - var i = 0 - var mul = 1 - var sub = value < 0 ? 1 : 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - - return offset + byteLength -} - -Buffer.prototype.writeIntBE = function (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkInt(this, - value, - offset, - byteLength, - Math.pow(2, 8 * byteLength - 1) - 1, - -Math.pow(2, 8 * byteLength - 1)) - } - - var i = byteLength - 1 - var mul = 1 - var sub = value < 0 ? 1 : 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = value - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - } else objectWriteUInt16(this, value, offset, true) - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = value - } else objectWriteUInt16(this, value, offset, false) - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else objectWriteUInt32(this, value, offset, true) - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = value - } else objectWriteUInt32(this, value, offset, false) - return offset + 4 -} - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (value > max || value < min) throw new RangeError('value is out of bounds') - if (offset + ext > buf.length) throw new RangeError('index out of range') - if (offset < 0) throw new RangeError('index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (target_start >= target.length) target_start = target.length - if (!target_start) target_start = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || source.length === 0) return 0 - - // Fatal error conditions - if (target_start < 0) - throw new RangeError('targetStart out of bounds') - if (start < 0 || start >= source.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < len; i++) { - target[i + target_start] = this[i + start] - } - } else { - target._set(this.subarray(start, start + len), target_start) - } - - return len -} - -// fill(value, start=0, end=buffer.length) -Buffer.prototype.fill = function (value, start, end) { - if (!value) value = 0 - if (!start) start = 0 - if (!end) end = this.length - - if (end < start) throw new RangeError('end < start') - - // Fill 0 bytes; we're done - if (end === start) return - if (this.length === 0) return - - if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') - if (end < 0 || end > this.length) throw new RangeError('end out of bounds') - - var i - if (typeof value === 'number') { - for (i = start; i < end; i++) { - this[i] = value - } - } else { - var bytes = utf8ToBytes(value.toString()) - var len = bytes.length - for (i = start; i < end; i++) { - this[i] = bytes[i % len] - } - } - - return this -} - -/** - * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. - * Added in Node 0.12. Only available in browsers that support ArrayBuffer. - */ -Buffer.prototype.toArrayBuffer = function () { - if (typeof Uint8Array !== 'undefined') { - if (Buffer.TYPED_ARRAY_SUPPORT) { - return (new Buffer(this)).buffer - } else { - var buf = new Uint8Array(this.length) - for (var i = 0, len = buf.length; i < len; i += 1) { - buf[i] = this[i] - } - return buf.buffer - } - } else { - throw new TypeError('Buffer.toArrayBuffer not supported in this browser') - } -} - -// HELPER FUNCTIONS -// ================ - -var BP = Buffer.prototype - -/** - * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods - */ -Buffer._augment = function (arr) { - arr.constructor = Buffer - arr._isBuffer = true - - // save reference to original Uint8Array get/set methods before overwriting - arr._get = arr.get - arr._set = arr.set - - // deprecated, will be removed in node 0.13+ - arr.get = BP.get - arr.set = BP.set - - arr.write = BP.write - arr.toString = BP.toString - arr.toLocaleString = BP.toString - arr.toJSON = BP.toJSON - arr.equals = BP.equals - arr.compare = BP.compare - arr.copy = BP.copy - arr.slice = BP.slice - arr.readUIntLE = BP.readUIntLE - arr.readUIntBE = BP.readUIntBE - arr.readUInt8 = BP.readUInt8 - arr.readUInt16LE = BP.readUInt16LE - arr.readUInt16BE = BP.readUInt16BE - arr.readUInt32LE = BP.readUInt32LE - arr.readUInt32BE = BP.readUInt32BE - arr.readIntLE = BP.readIntLE - arr.readIntBE = BP.readIntBE - arr.readInt8 = BP.readInt8 - arr.readInt16LE = BP.readInt16LE - arr.readInt16BE = BP.readInt16BE - arr.readInt32LE = BP.readInt32LE - arr.readInt32BE = BP.readInt32BE - arr.readFloatLE = BP.readFloatLE - arr.readFloatBE = BP.readFloatBE - arr.readDoubleLE = BP.readDoubleLE - arr.readDoubleBE = BP.readDoubleBE - arr.writeUInt8 = BP.writeUInt8 - arr.writeUIntLE = BP.writeUIntLE - arr.writeUIntBE = BP.writeUIntBE - arr.writeUInt16LE = BP.writeUInt16LE - arr.writeUInt16BE = BP.writeUInt16BE - arr.writeUInt32LE = BP.writeUInt32LE - arr.writeUInt32BE = BP.writeUInt32BE - arr.writeIntLE = BP.writeIntLE - arr.writeIntBE = BP.writeIntBE - arr.writeInt8 = BP.writeInt8 - arr.writeInt16LE = BP.writeInt16LE - arr.writeInt16BE = BP.writeInt16BE - arr.writeInt32LE = BP.writeInt32LE - arr.writeInt32BE = BP.writeInt32BE - arr.writeFloatLE = BP.writeFloatLE - arr.writeFloatBE = BP.writeFloatBE - arr.writeDoubleLE = BP.writeDoubleLE - arr.writeDoubleBE = BP.writeDoubleBE - arr.fill = BP.fill - arr.inspect = BP.inspect - arr.toArrayBuffer = BP.toArrayBuffer - - return arr -} - -var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g - -function base64clean (str) { - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} - -function isArrayish (subject) { - return isArray(subject) || Buffer.isBuffer(subject) || - subject && typeof subject === 'object' && - typeof subject.length === 'number' -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes(string, units) { - var codePoint, length = string.length - var leadSurrogate = null - units = units || Infinity - var bytes = [] - var i = 0 - - for (; i 0xD7FF && codePoint < 0xE000) { - - // last char was a lead - if (leadSurrogate) { - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } - - // valid surrogate pair - else { - codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 - leadSurrogate = null - } - } - - // no lead yet - else { - - // unexpected trail - if (codePoint > 0xDBFF) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // unpaired lead - else if (i + 1 === length) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - else { - leadSurrogate = codePoint - continue - } - } - } - - // valid bmp char, but last char was a lead - else if (leadSurrogate) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = null - } - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } - else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ); - } - else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ); - } - else if (codePoint < 0x200000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ); - } - else { - throw new Error('Invalid code point') - } - } - - return bytes -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; i++) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; i++) { - - if ((units -= 2) < 0) break - - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} - -function blitBuffer (src, dst, offset, length, unitSize) { - if (unitSize) length -= length % unitSize; - for (var i = 0; i < length; i++) { - if ((i + offset >= dst.length) || (i >= src.length)) - break - dst[i + offset] = src[i] - } - return i -} - -function decodeUtf8Char (str) { - try { - return decodeURIComponent(str) - } catch (err) { - return String.fromCharCode(0xFFFD) // UTF 8 invalid char - } -} - -},{"base64-js":36,"ieee754":37,"is-array":38}],36:[function(require,module,exports){ -var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -;(function (exports) { - 'use strict'; - - var Arr = (typeof Uint8Array !== 'undefined') - ? Uint8Array - : Array - - var PLUS = '+'.charCodeAt(0) - var SLASH = '/'.charCodeAt(0) - var NUMBER = '0'.charCodeAt(0) - var LOWER = 'a'.charCodeAt(0) - var UPPER = 'A'.charCodeAt(0) - var PLUS_URL_SAFE = '-'.charCodeAt(0) - var SLASH_URL_SAFE = '_'.charCodeAt(0) - - function decode (elt) { - var code = elt.charCodeAt(0) - if (code === PLUS || - code === PLUS_URL_SAFE) - return 62 // '+' - if (code === SLASH || - code === SLASH_URL_SAFE) - return 63 // '/' - if (code < NUMBER) - return -1 //no match - if (code < NUMBER + 10) - return code - NUMBER + 26 + 26 - if (code < UPPER + 26) - return code - UPPER - if (code < LOWER + 26) - return code - LOWER + 26 - } - - function b64ToByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - - if (b64.length % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - var len = b64.length - placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 - - // base64 is 4/3 + up to two characters of the original data - arr = new Arr(b64.length * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? b64.length - 4 : b64.length - - var L = 0 - - function push (v) { - arr[L++] = v - } - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) - push((tmp & 0xFF0000) >> 16) - push((tmp & 0xFF00) >> 8) - push(tmp & 0xFF) - } - - if (placeHolders === 2) { - tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) - push(tmp & 0xFF) - } else if (placeHolders === 1) { - tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) - push((tmp >> 8) & 0xFF) - push(tmp & 0xFF) - } - - return arr - } - - function uint8ToBase64 (uint8) { - var i, - extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes - output = "", - temp, length - - function encode (num) { - return lookup.charAt(num) - } - - function tripletToBase64 (num) { - return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) - } - - // go through the array every three bytes, we'll deal with trailing stuff later - for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { - temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output += tripletToBase64(temp) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - switch (extraBytes) { - case 1: - temp = uint8[uint8.length - 1] - output += encode(temp >> 2) - output += encode((temp << 4) & 0x3F) - output += '==' - break - case 2: - temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) - output += encode(temp >> 10) - output += encode((temp >> 4) & 0x3F) - output += encode((temp << 2) & 0x3F) - output += '=' - break - } - - return output - } - - exports.toByteArray = b64ToByteArray - exports.fromByteArray = uint8ToBase64 -}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) - -},{}],37:[function(require,module,exports){ -exports.read = function(buffer, offset, isLE, mLen, nBytes) { - var e, m, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - nBits = -7, - i = isLE ? (nBytes - 1) : 0, - d = isLE ? -1 : 1, - s = buffer[offset + i]; - - i += d; - - e = s & ((1 << (-nBits)) - 1); - s >>= (-nBits); - nBits += eLen; - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); - - m = e & ((1 << (-nBits)) - 1); - e >>= (-nBits); - nBits += mLen; - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); - - if (e === 0) { - e = 1 - eBias; - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity); - } else { - m = m + Math.pow(2, mLen); - e = e - eBias; - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen); -}; - -exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), - i = isLE ? 0 : (nBytes - 1), - d = isLE ? 1 : -1, - s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; - - value = Math.abs(value); - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0; - e = eMax; - } else { - e = Math.floor(Math.log(value) / Math.LN2); - if (value * (c = Math.pow(2, -e)) < 1) { - e--; - c *= 2; - } - if (e + eBias >= 1) { - value += rt / c; - } else { - value += rt * Math.pow(2, 1 - eBias); - } - if (value * c >= 2) { - e++; - c /= 2; - } - - if (e + eBias >= eMax) { - m = 0; - e = eMax; - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen); - e = e + eBias; - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); - e = 0; - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); - - e = (e << mLen) | m; - eLen += mLen; - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); - - buffer[offset + i - d] |= s * 128; -}; - -},{}],38:[function(require,module,exports){ - -/** - * isArray - */ - -var isArray = Array.isArray; - -/** - * toString - */ - -var str = Object.prototype.toString; - -/** - * Whether or not the given `val` - * is an array. - * - * example: - * - * isArray([]); - * // > true - * isArray(arguments); - * // > false - * isArray(''); - * // > false - * - * @param {mixed} val - * @return {bool} - */ - -module.exports = isArray || function (val) { - return !! val && '[object Array]' == str.call(val); -}; - -},{}],39:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],40:[function(require,module,exports){ -var http = module.exports; -var EventEmitter = require('events').EventEmitter; -var Request = require('./lib/request'); -var url = require('url') - -http.request = function (params, cb) { - if (typeof params === 'string') { - params = url.parse(params) - } - if (!params) params = {}; - if (!params.host && !params.port) { - params.port = parseInt(window.location.port, 10); - } - if (!params.host && params.hostname) { - params.host = params.hostname; - } - - if (!params.protocol) { - if (params.scheme) { - params.protocol = params.scheme + ':'; - } else { - params.protocol = window.location.protocol; - } - } - - if (!params.host) { - params.host = window.location.hostname || window.location.host; - } - if (/:/.test(params.host)) { - if (!params.port) { - params.port = params.host.split(':')[1]; - } - params.host = params.host.split(':')[0]; - } - if (!params.port) params.port = params.protocol == 'https:' ? 443 : 80; - - var req = new Request(new xhrHttp, params); - if (cb) req.on('response', cb); - return req; -}; - -http.get = function (params, cb) { - params.method = 'GET'; - var req = http.request(params, cb); - req.end(); - return req; -}; - -http.Agent = function () {}; -http.Agent.defaultMaxSockets = 4; - -var xhrHttp = (function () { - if (typeof window === 'undefined') { - throw new Error('no window object present'); - } - else if (window.XMLHttpRequest) { - return window.XMLHttpRequest; - } - else if (window.ActiveXObject) { - var axs = [ - 'Msxml2.XMLHTTP.6.0', - 'Msxml2.XMLHTTP.3.0', - 'Microsoft.XMLHTTP' - ]; - for (var i = 0; i < axs.length; i++) { - try { - var ax = new(window.ActiveXObject)(axs[i]); - return function () { - if (ax) { - var ax_ = ax; - ax = null; - return ax_; - } - else { - return new(window.ActiveXObject)(axs[i]); - } - }; - } - catch (e) {} - } - throw new Error('ajax not supported in this browser') - } - else { - throw new Error('ajax not supported in this browser'); - } -})(); - -http.STATUS_CODES = { - 100 : 'Continue', - 101 : 'Switching Protocols', - 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918 - 200 : 'OK', - 201 : 'Created', - 202 : 'Accepted', - 203 : 'Non-Authoritative Information', - 204 : 'No Content', - 205 : 'Reset Content', - 206 : 'Partial Content', - 207 : 'Multi-Status', // RFC 4918 - 300 : 'Multiple Choices', - 301 : 'Moved Permanently', - 302 : 'Moved Temporarily', - 303 : 'See Other', - 304 : 'Not Modified', - 305 : 'Use Proxy', - 307 : 'Temporary Redirect', - 400 : 'Bad Request', - 401 : 'Unauthorized', - 402 : 'Payment Required', - 403 : 'Forbidden', - 404 : 'Not Found', - 405 : 'Method Not Allowed', - 406 : 'Not Acceptable', - 407 : 'Proxy Authentication Required', - 408 : 'Request Time-out', - 409 : 'Conflict', - 410 : 'Gone', - 411 : 'Length Required', - 412 : 'Precondition Failed', - 413 : 'Request Entity Too Large', - 414 : 'Request-URI Too Large', - 415 : 'Unsupported Media Type', - 416 : 'Requested Range Not Satisfiable', - 417 : 'Expectation Failed', - 418 : 'I\'m a teapot', // RFC 2324 - 422 : 'Unprocessable Entity', // RFC 4918 - 423 : 'Locked', // RFC 4918 - 424 : 'Failed Dependency', // RFC 4918 - 425 : 'Unordered Collection', // RFC 4918 - 426 : 'Upgrade Required', // RFC 2817 - 428 : 'Precondition Required', // RFC 6585 - 429 : 'Too Many Requests', // RFC 6585 - 431 : 'Request Header Fields Too Large',// RFC 6585 - 500 : 'Internal Server Error', - 501 : 'Not Implemented', - 502 : 'Bad Gateway', - 503 : 'Service Unavailable', - 504 : 'Gateway Time-out', - 505 : 'HTTP Version Not Supported', - 506 : 'Variant Also Negotiates', // RFC 2295 - 507 : 'Insufficient Storage', // RFC 4918 - 509 : 'Bandwidth Limit Exceeded', - 510 : 'Not Extended', // RFC 2774 - 511 : 'Network Authentication Required' // RFC 6585 -}; -},{"./lib/request":41,"events":39,"url":66}],41:[function(require,module,exports){ -var Stream = require('stream'); -var Response = require('./response'); -var Base64 = require('Base64'); -var inherits = require('inherits'); - -var Request = module.exports = function (xhr, params) { - var self = this; - self.writable = true; - self.xhr = xhr; - self.body = []; - - self.uri = (params.protocol || 'http:') + '//' - + params.host - + (params.port ? ':' + params.port : '') - + (params.path || '/') - ; - - if (typeof params.withCredentials === 'undefined') { - params.withCredentials = true; - } - - try { xhr.withCredentials = params.withCredentials } - catch (e) {} - - if (params.responseType) try { xhr.responseType = params.responseType } - catch (e) {} - - xhr.open( - params.method || 'GET', - self.uri, - true - ); - - xhr.onerror = function(event) { - self.emit('error', new Error('Network error')); - }; - - self._headers = {}; - - if (params.headers) { - var keys = objectKeys(params.headers); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (!self.isSafeRequestHeader(key)) continue; - var value = params.headers[key]; - self.setHeader(key, value); - } - } - - if (params.auth) { - //basic auth - this.setHeader('Authorization', 'Basic ' + Base64.btoa(params.auth)); - } - - var res = new Response; - res.on('close', function () { - self.emit('close'); - }); - - res.on('ready', function () { - self.emit('response', res); - }); - - res.on('error', function (err) { - self.emit('error', err); - }); - - xhr.onreadystatechange = function () { - // Fix for IE9 bug - // SCRIPT575: Could not complete the operation due to error c00c023f - // It happens when a request is aborted, calling the success callback anyway with readyState === 4 - if (xhr.__aborted) return; - res.handle(xhr); - }; -}; - -inherits(Request, Stream); - -Request.prototype.setHeader = function (key, value) { - this._headers[key.toLowerCase()] = value -}; - -Request.prototype.getHeader = function (key) { - return this._headers[key.toLowerCase()] -}; - -Request.prototype.removeHeader = function (key) { - delete this._headers[key.toLowerCase()] -}; - -Request.prototype.write = function (s) { - this.body.push(s); -}; - -Request.prototype.destroy = function (s) { - this.xhr.__aborted = true; - this.xhr.abort(); - this.emit('close'); -}; - -Request.prototype.end = function (s) { - if (s !== undefined) this.body.push(s); - - var keys = objectKeys(this._headers); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var value = this._headers[key]; - if (isArray(value)) { - for (var j = 0; j < value.length; j++) { - this.xhr.setRequestHeader(key, value[j]); - } - } - else this.xhr.setRequestHeader(key, value) - } - - if (this.body.length === 0) { - this.xhr.send(''); - } - else if (typeof this.body[0] === 'string') { - this.xhr.send(this.body.join('')); - } - else if (isArray(this.body[0])) { - var body = []; - for (var i = 0; i < this.body.length; i++) { - body.push.apply(body, this.body[i]); - } - this.xhr.send(body); - } - else if (/Array/.test(Object.prototype.toString.call(this.body[0]))) { - var len = 0; - for (var i = 0; i < this.body.length; i++) { - len += this.body[i].length; - } - var body = new(this.body[0].constructor)(len); - var k = 0; - - for (var i = 0; i < this.body.length; i++) { - var b = this.body[i]; - for (var j = 0; j < b.length; j++) { - body[k++] = b[j]; - } - } - this.xhr.send(body); - } - else if (isXHR2Compatible(this.body[0])) { - this.xhr.send(this.body[0]); - } - else { - var body = ''; - for (var i = 0; i < this.body.length; i++) { - body += this.body[i].toString(); - } - this.xhr.send(body); - } -}; - -// Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html -Request.unsafeHeaders = [ - "accept-charset", - "accept-encoding", - "access-control-request-headers", - "access-control-request-method", - "connection", - "content-length", - "cookie", - "cookie2", - "content-transfer-encoding", - "date", - "expect", - "host", - "keep-alive", - "origin", - "referer", - "te", - "trailer", - "transfer-encoding", - "upgrade", - "user-agent", - "via" -]; - -Request.prototype.isSafeRequestHeader = function (headerName) { - if (!headerName) return false; - return indexOf(Request.unsafeHeaders, headerName.toLowerCase()) === -1; -}; - -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) keys.push(key); - return keys; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -var indexOf = function (xs, x) { - if (xs.indexOf) return xs.indexOf(x); - for (var i = 0; i < xs.length; i++) { - if (xs[i] === x) return i; - } - return -1; -}; - -var isXHR2Compatible = function (obj) { - if (typeof Blob !== 'undefined' && obj instanceof Blob) return true; - if (typeof ArrayBuffer !== 'undefined' && obj instanceof ArrayBuffer) return true; - if (typeof FormData !== 'undefined' && obj instanceof FormData) return true; -}; - -},{"./response":42,"Base64":43,"inherits":45,"stream":64}],42:[function(require,module,exports){ -var Stream = require('stream'); -var util = require('util'); - -var Response = module.exports = function (res) { - this.offset = 0; - this.readable = true; -}; - -util.inherits(Response, Stream); - -var capable = { - streaming : true, - status2 : true -}; - -function parseHeaders (res) { - var lines = res.getAllResponseHeaders().split(/\r?\n/); - var headers = {}; - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line === '') continue; - - var m = line.match(/^([^:]+):\s*(.*)/); - if (m) { - var key = m[1].toLowerCase(), value = m[2]; - - if (headers[key] !== undefined) { - - if (isArray(headers[key])) { - headers[key].push(value); - } - else { - headers[key] = [ headers[key], value ]; - } - } - else { - headers[key] = value; - } - } - else { - headers[line] = true; - } - } - return headers; -} - -Response.prototype.getResponse = function (xhr) { - var respType = String(xhr.responseType).toLowerCase(); - if (respType === 'blob') return xhr.responseBlob || xhr.response; - if (respType === 'arraybuffer') return xhr.response; - return xhr.responseText; -} - -Response.prototype.getHeader = function (key) { - return this.headers[key.toLowerCase()]; -}; - -Response.prototype.handle = function (res) { - if (res.readyState === 2 && capable.status2) { - try { - this.statusCode = res.status; - this.headers = parseHeaders(res); - } - catch (err) { - capable.status2 = false; - } - - if (capable.status2) { - this.emit('ready'); - } - } - else if (capable.streaming && res.readyState === 3) { - try { - if (!this.statusCode) { - this.statusCode = res.status; - this.headers = parseHeaders(res); - this.emit('ready'); - } - } - catch (err) {} - - try { - this._emitData(res); - } - catch (err) { - capable.streaming = false; - } - } - else if (res.readyState === 4) { - if (!this.statusCode) { - this.statusCode = res.status; - this.emit('ready'); - } - this._emitData(res); - - if (res.error) { - this.emit('error', this.getResponse(res)); - } - else this.emit('end'); - - this.emit('close'); - } -}; - -Response.prototype._emitData = function (res) { - var respBody = this.getResponse(res); - if (respBody.toString().match(/ArrayBuffer/)) { - this.emit('data', new Uint8Array(respBody, this.offset)); - this.offset = respBody.byteLength; - return; - } - if (respBody.length > this.offset) { - this.emit('data', respBody.slice(this.offset)); - this.offset = respBody.length; - } -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -},{"stream":64,"util":68}],43:[function(require,module,exports){ -;(function () { - - var object = typeof exports != 'undefined' ? exports : this; // #8: web workers - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - - function InvalidCharacterError(message) { - this.message = message; - } - InvalidCharacterError.prototype = new Error; - InvalidCharacterError.prototype.name = 'InvalidCharacterError'; - - // encoder - // [https://gist.github.com/999166] by [https://github.com/nignag] - object.btoa || ( - object.btoa = function (input) { - for ( - // initialize result and counter - var block, charCode, idx = 0, map = chars, output = ''; - // if the next input index does not exist: - // change the mapping table to "=" - // check if d has no fractional digits - input.charAt(idx | 0) || (map = '=', idx % 1); - // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8 - output += map.charAt(63 & block >> 8 - idx % 1 * 8) - ) { - charCode = input.charCodeAt(idx += 3/4); - if (charCode > 0xFF) { - throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."); - } - block = block << 8 | charCode; - } - return output; - }); - - // decoder - // [https://gist.github.com/1020396] by [https://github.com/atk] - object.atob || ( - object.atob = function (input) { - input = input.replace(/=+$/, ''); - if (input.length % 4 == 1) { - throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded."); - } - for ( - // initialize result and counters - var bc = 0, bs, buffer, idx = 0, output = ''; - // get next character - buffer = input.charAt(idx++); - // character found in table? initialize bit storage and add its ascii value; - ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, - // and if not first of each 4 characters, - // convert the first 8 bits to one ascii character - bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 - ) { - // try to find character in table (0-63, not found => -1) - buffer = chars.indexOf(buffer); - } - return output; - }); - -}()); - -},{}],44:[function(require,module,exports){ -var http = require('http'); - -var https = module.exports; - -for (var key in http) { - if (http.hasOwnProperty(key)) https[key] = http[key]; -}; - -https.request = function (params, cb) { - if (!params) params = {}; - params.scheme = 'https'; - return http.request.call(this, params, cb); -} - -},{"http":40}],45:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],46:[function(require,module,exports){ -module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; -}; - -},{}],47:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":48}],48:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; - -function drainQueue() { - if (draining) { - return; - } - draining = true; - var currentQueue; - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - var i = -1; - while (++i < len) { - currentQueue[i](); - } - len = queue.length; - } - draining = false; -} -process.nextTick = function (fun) { - queue.push(fun); - if (!draining) { - setTimeout(drainQueue, 0); - } -}; - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],49:[function(require,module,exports){ -(function (global){ -/*! http://mths.be/punycode v1.2.4 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports; - var freeModule = typeof module == 'object' && module && - module.exports == freeExports && module; - var freeGlobal = typeof global == 'object' && global; - if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - while (length--) { - array[length] = fn(array[length]); - } - return array; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings. - * @private - * @param {String} domain The domain name. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - return map(string.split(regexSeparators), fn).join('.'); - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols to a Punycode string of ASCII-only - * symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name to Unicode. Only the - * Punycoded parts of the domain name will be converted, i.e. it doesn't - * matter if you call it on a string that has already been converted to - * Unicode. - * @memberOf punycode - * @param {String} domain The Punycode domain name to convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(domain) { - return mapDomain(domain, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name to Punycode. Only the - * non-ASCII parts of the domain name will be converted, i.e. it doesn't - * matter if you call it with a domain that's already in ASCII. - * @memberOf punycode - * @param {String} domain The domain name to convert, as a Unicode string. - * @returns {String} The Punycode representation of the given domain name. - */ - function toASCII(domain) { - return mapDomain(domain, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.2.4', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define('punycode', function() { - return punycode; - }); - } else if (freeExports && !freeExports.nodeType) { - if (freeModule) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],50:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -},{}],51:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - -},{}],52:[function(require,module,exports){ -'use strict'; - -exports.decode = exports.parse = require('./decode'); -exports.encode = exports.stringify = require('./encode'); - -},{"./decode":50,"./encode":51}],53:[function(require,module,exports){ -module.exports = require("./lib/_stream_duplex.js") - -},{"./lib/_stream_duplex.js":54}],54:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - -module.exports = Duplex; - -/**/ -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) keys.push(key); - return keys; -} -/**/ - - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var Readable = require('./_stream_readable'); -var Writable = require('./_stream_writable'); - -util.inherits(Duplex, Readable); - -forEach(objectKeys(Writable.prototype), function(method) { - if (!Duplex.prototype[method]) - Duplex.prototype[method] = Writable.prototype[method]; -}); - -function Duplex(options) { - if (!(this instanceof Duplex)) - return new Duplex(options); - - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) - this.readable = false; - - if (options && options.writable === false) - this.writable = false; - - this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) - this.allowHalfOpen = false; - - this.once('end', onend); -} - -// the no-half-open enforcer -function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) - return; - - // no more data can be written. - // But allow more writes to happen in this tick. - process.nextTick(this.end.bind(this)); -} - -function forEach (xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -}).call(this,require('_process')) -},{"./_stream_readable":56,"./_stream_writable":58,"_process":48,"core-util-is":59,"inherits":45}],55:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. - -module.exports = PassThrough; - -var Transform = require('./_stream_transform'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(PassThrough, Transform); - -function PassThrough(options) { - if (!(this instanceof PassThrough)) - return new PassThrough(options); - - Transform.call(this, options); -} - -PassThrough.prototype._transform = function(chunk, encoding, cb) { - cb(null, chunk); -}; - -},{"./_stream_transform":57,"core-util-is":59,"inherits":45}],56:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = Readable; - -/**/ -var isArray = require('isarray'); -/**/ - - -/**/ -var Buffer = require('buffer').Buffer; -/**/ - -Readable.ReadableState = ReadableState; - -var EE = require('events').EventEmitter; - -/**/ -if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { - return emitter.listeners(type).length; -}; -/**/ - -var Stream = require('stream'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var StringDecoder; - -util.inherits(Readable, Stream); - -function ReadableState(options, stream) { - options = options || {}; - - // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - var hwm = options.highWaterMark; - this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - this.buffer = []; - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = false; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // In streams that never have any data, and do push(null) right away, - // the consumer can miss the 'end' event if they do some I/O before - // consuming the stream. So, we don't emit('end') until some reading - // happens. - this.calledRead = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, becuase any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - - - // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away - this.objectMode = !!options.objectMode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // when piping, we only care about 'readable' events that happen - // after read()ing all the bytes and not getting any pushback. - this.ranOut = false; - - // the number of writers that are awaiting a drain event in .pipe()s - this.awaitDrain = 0; - - // if true, a maybeReadMore has been scheduled - this.readingMore = false; - - this.decoder = null; - this.encoding = null; - if (options.encoding) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } -} - -function Readable(options) { - if (!(this instanceof Readable)) - return new Readable(options); - - this._readableState = new ReadableState(options, this); - - // legacy - this.readable = true; - - Stream.call(this); -} - -// Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. -Readable.prototype.push = function(chunk, encoding) { - var state = this._readableState; - - if (typeof chunk === 'string' && !state.objectMode) { - encoding = encoding || state.defaultEncoding; - if (encoding !== state.encoding) { - chunk = new Buffer(chunk, encoding); - encoding = ''; - } - } - - return readableAddChunk(this, state, chunk, encoding, false); -}; - -// Unshift should *always* be something directly out of read() -Readable.prototype.unshift = function(chunk) { - var state = this._readableState; - return readableAddChunk(this, state, chunk, '', true); -}; - -function readableAddChunk(stream, state, chunk, encoding, addToFront) { - var er = chunkInvalid(state, chunk); - if (er) { - stream.emit('error', er); - } else if (chunk === null || chunk === undefined) { - state.reading = false; - if (!state.ended) - onEofChunk(stream, state); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (state.ended && !addToFront) { - var e = new Error('stream.push() after EOF'); - stream.emit('error', e); - } else if (state.endEmitted && addToFront) { - var e = new Error('stream.unshift() after end event'); - stream.emit('error', e); - } else { - if (state.decoder && !addToFront && !encoding) - chunk = state.decoder.write(chunk); - - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) { - state.buffer.unshift(chunk); - } else { - state.reading = false; - state.buffer.push(chunk); - } - - if (state.needReadable) - emitReadable(stream); - - maybeReadMore(stream, state); - } - } else if (!addToFront) { - state.reading = false; - } - - return needMoreData(state); -} - - - -// if it's past the high water mark, we can push in some more. -// Also, if we have no data yet, we can stand some -// more bytes. This is to work around cases where hwm=0, -// such as the repl. Also, if the push() triggered a -// readable event, and the user called read(largeNumber) such that -// needReadable was set, then we ought to push more, so that another -// 'readable' event will be triggered. -function needMoreData(state) { - return !state.ended && - (state.needReadable || - state.length < state.highWaterMark || - state.length === 0); -} - -// backwards compatibility. -Readable.prototype.setEncoding = function(enc) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; - this._readableState.decoder = new StringDecoder(enc); - this._readableState.encoding = enc; -}; - -// Don't raise the hwm > 128MB -var MAX_HWM = 0x800000; -function roundUpToNextPowerOf2(n) { - if (n >= MAX_HWM) { - n = MAX_HWM; - } else { - // Get the next highest power of 2 - n--; - for (var p = 1; p < 32; p <<= 1) n |= n >> p; - n++; - } - return n; -} - -function howMuchToRead(n, state) { - if (state.length === 0 && state.ended) - return 0; - - if (state.objectMode) - return n === 0 ? 0 : 1; - - if (n === null || isNaN(n)) { - // only flow one buffer at a time - if (state.flowing && state.buffer.length) - return state.buffer[0].length; - else - return state.length; - } - - if (n <= 0) - return 0; - - // If we're asking for more than the target buffer level, - // then raise the water mark. Bump up to the next highest - // power of 2, to prevent increasing it excessively in tiny - // amounts. - if (n > state.highWaterMark) - state.highWaterMark = roundUpToNextPowerOf2(n); - - // don't have that much. return null, unless we've ended. - if (n > state.length) { - if (!state.ended) { - state.needReadable = true; - return 0; - } else - return state.length; - } - - return n; -} - -// you can override either this method, or the async _read(n) below. -Readable.prototype.read = function(n) { - var state = this._readableState; - state.calledRead = true; - var nOrig = n; - var ret; - - if (typeof n !== 'number' || n > 0) - state.emittedReadable = false; - - // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - if (n === 0 && - state.needReadable && - (state.length >= state.highWaterMark || state.ended)) { - emitReadable(this); - return null; - } - - n = howMuchToRead(n, state); - - // if we've ended, and we're now clear, then finish it up. - if (n === 0 && state.ended) { - ret = null; - - // In cases where the decoder did not receive enough data - // to produce a full chunk, then immediately received an - // EOF, state.buffer will contain [, ]. - // howMuchToRead will see this and coerce the amount to - // read to zero (because it's looking at the length of the - // first in state.buffer), and we'll end up here. - // - // This can only happen via state.decoder -- no other venue - // exists for pushing a zero-length chunk into state.buffer - // and triggering this behavior. In this case, we return our - // remaining data and end the stream, if appropriate. - if (state.length > 0 && state.decoder) { - ret = fromList(n, state); - state.length -= ret.length; - } - - if (state.length === 0) - endReadable(this); - - return ret; - } - - // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - - // if we need a readable event, then we need to do some reading. - var doRead = state.needReadable; - - // if we currently have less than the highWaterMark, then also read some - if (state.length - n <= state.highWaterMark) - doRead = true; - - // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. - if (state.ended || state.reading) - doRead = false; - - if (doRead) { - state.reading = true; - state.sync = true; - // if the length is currently zero, then we *need* a readable event. - if (state.length === 0) - state.needReadable = true; - // call internal read method - this._read(state.highWaterMark); - state.sync = false; - } - - // If _read called its callback synchronously, then `reading` - // will be false, and we need to re-evaluate how much data we - // can return to the user. - if (doRead && !state.reading) - n = howMuchToRead(nOrig, state); - - if (n > 0) - ret = fromList(n, state); - else - ret = null; - - if (ret === null) { - state.needReadable = true; - n = 0; - } - - state.length -= n; - - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (state.length === 0 && !state.ended) - state.needReadable = true; - - // If we happened to read() exactly the remaining amount in the - // buffer, and the EOF has been seen at this point, then make sure - // that we emit 'end' on the very next tick. - if (state.ended && !state.endEmitted && state.length === 0) - endReadable(this); - - return ret; -}; - -function chunkInvalid(state, chunk) { - var er = null; - if (!Buffer.isBuffer(chunk) && - 'string' !== typeof chunk && - chunk !== null && - chunk !== undefined && - !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - return er; -} - - -function onEofChunk(stream, state) { - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - state.ended = true; - - // if we've ended and we have some data left, then emit - // 'readable' now to make sure it gets picked up. - if (state.length > 0) - emitReadable(stream); - else - endReadable(stream); -} - -// Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. -function emitReadable(stream) { - var state = stream._readableState; - state.needReadable = false; - if (state.emittedReadable) - return; - - state.emittedReadable = true; - if (state.sync) - process.nextTick(function() { - emitReadable_(stream); - }); - else - emitReadable_(stream); -} - -function emitReadable_(stream) { - stream.emit('readable'); -} - - -// at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - process.nextTick(function() { - maybeReadMore_(stream, state); - }); - } -} - -function maybeReadMore_(stream, state) { - var len = state.length; - while (!state.reading && !state.flowing && !state.ended && - state.length < state.highWaterMark) { - stream.read(0); - if (len === state.length) - // didn't get any data, stop spinning. - break; - else - len = state.length; - } - state.readingMore = false; -} - -// abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function(n) { - this.emit('error', new Error('not implemented')); -}; - -Readable.prototype.pipe = function(dest, pipeOpts) { - var src = this; - var state = this._readableState; - - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; - case 1: - state.pipes = [state.pipes, dest]; - break; - default: - state.pipes.push(dest); - break; - } - state.pipesCount += 1; - - var doEnd = (!pipeOpts || pipeOpts.end !== false) && - dest !== process.stdout && - dest !== process.stderr; - - var endFn = doEnd ? onend : cleanup; - if (state.endEmitted) - process.nextTick(endFn); - else - src.once('end', endFn); - - dest.on('unpipe', onunpipe); - function onunpipe(readable) { - if (readable !== src) return; - cleanup(); - } - - function onend() { - dest.end(); - } - - // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - - function cleanup() { - // cleanup event handlers once the pipe is broken - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', cleanup); - - // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - if (!dest._writableState || dest._writableState.needDrain) - ondrain(); - } - - // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. - function onerror(er) { - unpipe(); - dest.removeListener('error', onerror); - if (EE.listenerCount(dest, 'error') === 0) - dest.emit('error', er); - } - // This is a brutally ugly hack to make sure that our error handler - // is attached before any userland ones. NEVER DO THIS. - if (!dest._events || !dest._events.error) - dest.on('error', onerror); - else if (isArray(dest._events.error)) - dest._events.error.unshift(onerror); - else - dest._events.error = [onerror, dest._events.error]; - - - - // Both close and finish should trigger unpipe, but only once. - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); - } - dest.once('close', onclose); - function onfinish() { - dest.removeListener('close', onclose); - unpipe(); - } - dest.once('finish', onfinish); - - function unpipe() { - src.unpipe(dest); - } - - // tell the dest that it's being piped to - dest.emit('pipe', src); - - // start the flow if it hasn't been started already. - if (!state.flowing) { - // the handler that waits for readable events after all - // the data gets sucked out in flow. - // This would be easier to follow with a .once() handler - // in flow(), but that is too slow. - this.on('readable', pipeOnReadable); - - state.flowing = true; - process.nextTick(function() { - flow(src); - }); - } - - return dest; -}; - -function pipeOnDrain(src) { - return function() { - var dest = this; - var state = src._readableState; - state.awaitDrain--; - if (state.awaitDrain === 0) - flow(src); - }; -} - -function flow(src) { - var state = src._readableState; - var chunk; - state.awaitDrain = 0; - - function write(dest, i, list) { - var written = dest.write(chunk); - if (false === written) { - state.awaitDrain++; - } - } - - while (state.pipesCount && null !== (chunk = src.read())) { - - if (state.pipesCount === 1) - write(state.pipes, 0, null); - else - forEach(state.pipes, write); - - src.emit('data', chunk); - - // if anyone needs a drain, then we have to wait for that. - if (state.awaitDrain > 0) - return; - } - - // if every destination was unpiped, either before entering this - // function, or in the while loop, then stop flowing. - // - // NB: This is a pretty rare edge case. - if (state.pipesCount === 0) { - state.flowing = false; - - // if there were data event listeners added, then switch to old mode. - if (EE.listenerCount(src, 'data') > 0) - emitDataEvents(src); - return; - } - - // at this point, no one needed a drain, so we just ran out of data - // on the next readable event, start it over again. - state.ranOut = true; -} - -function pipeOnReadable() { - if (this._readableState.ranOut) { - this._readableState.ranOut = false; - flow(this); - } -} - - -Readable.prototype.unpipe = function(dest) { - var state = this._readableState; - - // if we're not piping anywhere, then do nothing. - if (state.pipesCount === 0) - return this; - - // just one destination. most common case. - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) - return this; - - if (!dest) - dest = state.pipes; - - // got a match. - state.pipes = null; - state.pipesCount = 0; - this.removeListener('readable', pipeOnReadable); - state.flowing = false; - if (dest) - dest.emit('unpipe', this); - return this; - } - - // slow case. multiple pipe destinations. - - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - this.removeListener('readable', pipeOnReadable); - state.flowing = false; - - for (var i = 0; i < len; i++) - dests[i].emit('unpipe', this); - return this; - } - - // try to find the right one. - var i = indexOf(state.pipes, dest); - if (i === -1) - return this; - - state.pipes.splice(i, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) - state.pipes = state.pipes[0]; - - dest.emit('unpipe', this); - - return this; -}; - -// set up data events if they are asked for -// Ensure readable listeners eventually get something -Readable.prototype.on = function(ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - - if (ev === 'data' && !this._readableState.flowing) - emitDataEvents(this); - - if (ev === 'readable' && this.readable) { - var state = this._readableState; - if (!state.readableListening) { - state.readableListening = true; - state.emittedReadable = false; - state.needReadable = true; - if (!state.reading) { - this.read(0); - } else if (state.length) { - emitReadable(this, state); - } - } - } - - return res; -}; -Readable.prototype.addListener = Readable.prototype.on; - -// pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. -Readable.prototype.resume = function() { - emitDataEvents(this); - this.read(0); - this.emit('resume'); -}; - -Readable.prototype.pause = function() { - emitDataEvents(this, true); - this.emit('pause'); -}; - -function emitDataEvents(stream, startPaused) { - var state = stream._readableState; - - if (state.flowing) { - // https://github.com/isaacs/readable-stream/issues/16 - throw new Error('Cannot switch to old mode now.'); - } - - var paused = startPaused || false; - var readable = false; - - // convert to an old-style stream. - stream.readable = true; - stream.pipe = Stream.prototype.pipe; - stream.on = stream.addListener = Stream.prototype.on; - - stream.on('readable', function() { - readable = true; - - var c; - while (!paused && (null !== (c = stream.read()))) - stream.emit('data', c); - - if (c === null) { - readable = false; - stream._readableState.needReadable = true; - } - }); - - stream.pause = function() { - paused = true; - this.emit('pause'); - }; - - stream.resume = function() { - paused = false; - if (readable) - process.nextTick(function() { - stream.emit('readable'); - }); - else - this.read(0); - this.emit('resume'); - }; - - // now make it start, just in case it hadn't already. - stream.emit('readable'); -} - -// wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. -Readable.prototype.wrap = function(stream) { - var state = this._readableState; - var paused = false; - - var self = this; - stream.on('end', function() { - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) - self.push(chunk); - } - - self.push(null); - }); - - stream.on('data', function(chunk) { - if (state.decoder) - chunk = state.decoder.write(chunk); - - // don't skip over falsy values in objectMode - //if (state.objectMode && util.isNullOrUndefined(chunk)) - if (state.objectMode && (chunk === null || chunk === undefined)) - return; - else if (!state.objectMode && (!chunk || !chunk.length)) - return; - - var ret = self.push(chunk); - if (!ret) { - paused = true; - stream.pause(); - } - }); - - // proxy all the other methods. - // important when wrapping filters and duplexes. - for (var i in stream) { - if (typeof stream[i] === 'function' && - typeof this[i] === 'undefined') { - this[i] = function(method) { return function() { - return stream[method].apply(stream, arguments); - }}(i); - } - } - - // proxy certain important events. - var events = ['error', 'close', 'destroy', 'pause', 'resume']; - forEach(events, function(ev) { - stream.on(ev, self.emit.bind(self, ev)); - }); - - // when we try to consume some more bytes, simply unpause the - // underlying stream. - self._read = function(n) { - if (paused) { - paused = false; - stream.resume(); - } - }; - - return self; -}; - - - -// exposed for testing purposes only. -Readable._fromList = fromList; - -// Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -function fromList(n, state) { - var list = state.buffer; - var length = state.length; - var stringMode = !!state.decoder; - var objectMode = !!state.objectMode; - var ret; - - // nothing in the list, definitely empty. - if (list.length === 0) - return null; - - if (length === 0) - ret = null; - else if (objectMode) - ret = list.shift(); - else if (!n || n >= length) { - // read it all, truncate the array. - if (stringMode) - ret = list.join(''); - else - ret = Buffer.concat(list, length); - list.length = 0; - } else { - // read just some of it. - if (n < list[0].length) { - // just take a part of the first list item. - // slice is the same for buffers and strings. - var buf = list[0]; - ret = buf.slice(0, n); - list[0] = buf.slice(n); - } else if (n === list[0].length) { - // first list is a perfect match - ret = list.shift(); - } else { - // complex case. - // we have enough to cover it, but it spans past the first buffer. - if (stringMode) - ret = ''; - else - ret = new Buffer(n); - - var c = 0; - for (var i = 0, l = list.length; i < l && c < n; i++) { - var buf = list[0]; - var cpy = Math.min(n - c, buf.length); - - if (stringMode) - ret += buf.slice(0, cpy); - else - buf.copy(ret, c, 0, cpy); - - if (cpy < buf.length) - list[0] = buf.slice(cpy); - else - list.shift(); - - c += cpy; - } - } - } - - return ret; -} - -function endReadable(stream) { - var state = stream._readableState; - - // If we get here before consuming all the bytes, then that is a - // bug in node. Should never happen. - if (state.length > 0) - throw new Error('endReadable called on non-empty stream'); - - if (!state.endEmitted && state.calledRead) { - state.ended = true; - process.nextTick(function() { - // Check that we didn't get one last unshift. - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); - } - }); - } -} - -function forEach (xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -function indexOf (xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; - } - return -1; -} - -}).call(this,require('_process')) -},{"_process":48,"buffer":35,"core-util-is":59,"events":39,"inherits":45,"isarray":46,"stream":64,"string_decoder/":65}],57:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. - -module.exports = Transform; - -var Duplex = require('./_stream_duplex'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(Transform, Duplex); - - -function TransformState(options, stream) { - this.afterTransform = function(er, data) { - return afterTransform(stream, er, data); - }; - - this.needTransform = false; - this.transforming = false; - this.writecb = null; - this.writechunk = null; -} - -function afterTransform(stream, er, data) { - var ts = stream._transformState; - ts.transforming = false; - - var cb = ts.writecb; - - if (!cb) - return stream.emit('error', new Error('no writecb in Transform class')); - - ts.writechunk = null; - ts.writecb = null; - - if (data !== null && data !== undefined) - stream.push(data); - - if (cb) - cb(er); - - var rs = stream._readableState; - rs.reading = false; - if (rs.needReadable || rs.length < rs.highWaterMark) { - stream._read(rs.highWaterMark); - } -} - - -function Transform(options) { - if (!(this instanceof Transform)) - return new Transform(options); - - Duplex.call(this, options); - - var ts = this._transformState = new TransformState(options, this); - - // when the writable side finishes, then flush out anything remaining. - var stream = this; - - // start out asking for a readable event once data is transformed. - this._readableState.needReadable = true; - - // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - this._readableState.sync = false; - - this.once('finish', function() { - if ('function' === typeof this._flush) - this._flush(function(er) { - done(stream, er); - }); - else - done(stream); - }); -} - -Transform.prototype.push = function(chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; - -// This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. -Transform.prototype._transform = function(chunk, encoding, cb) { - throw new Error('not implemented'); -}; - -Transform.prototype._write = function(chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || - rs.needReadable || - rs.length < rs.highWaterMark) - this._read(rs.highWaterMark); - } -}; - -// Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. -Transform.prototype._read = function(n) { - var ts = this._transformState; - - if (ts.writechunk !== null && ts.writecb && !ts.transforming) { - ts.transforming = true; - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); - } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; - } -}; - - -function done(stream, er) { - if (er) - return stream.emit('error', er); - - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided - var ws = stream._writableState; - var rs = stream._readableState; - var ts = stream._transformState; - - if (ws.length) - throw new Error('calling transform done when ws.length != 0'); - - if (ts.transforming) - throw new Error('calling transform done when still transforming'); - - return stream.push(null); -} - -},{"./_stream_duplex":54,"core-util-is":59,"inherits":45}],58:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// A bit simpler than readable streams. -// Implement an async ._write(chunk, cb), and it'll handle all -// the drain event emission and buffering. - -module.exports = Writable; - -/**/ -var Buffer = require('buffer').Buffer; -/**/ - -Writable.WritableState = WritableState; - - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var Stream = require('stream'); - -util.inherits(Writable, Stream); - -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; -} - -function WritableState(options, stream) { - options = options || {}; - - // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - var hwm = options.highWaterMark; - this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; - - // object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options.objectMode; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - this.needDrain = false; - // at the start of calling end() - this.ending = false; - // when end() has been called, and returned - this.ended = false; - // when 'finish' is emitted - this.finished = false; - - // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // a flag to see when we're in the middle of a write. - this.writing = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, becuase any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // the callback that's passed to _write(chunk,cb) - this.onwrite = function(er) { - onwrite(stream, er); - }; - - // the callback that the user supplies to write(chunk,encoding,cb) - this.writecb = null; - - // the amount that is being written when _write is called. - this.writelen = 0; - - this.buffer = []; - - // True if the error was already emitted and should not be thrown again - this.errorEmitted = false; -} - -function Writable(options) { - var Duplex = require('./_stream_duplex'); - - // Writable ctor is applied to Duplexes, though they're not - // instanceof Writable, they're instanceof Readable. - if (!(this instanceof Writable) && !(this instanceof Duplex)) - return new Writable(options); - - this._writableState = new WritableState(options, this); - - // legacy. - this.writable = true; - - Stream.call(this); -} - -// Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function() { - this.emit('error', new Error('Cannot pipe. Not readable.')); -}; - - -function writeAfterEnd(stream, state, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream.emit('error', er); - process.nextTick(function() { - cb(er); - }); -} - -// If we get something that is not a buffer, string, null, or undefined, -// and we're not in objectMode, then that's an error. -// Otherwise stream chunks are all considered to be of length=1, and the -// watermarks determine how many objects to keep in the buffer, rather than -// how many bytes or characters. -function validChunk(stream, state, chunk, cb) { - var valid = true; - if (!Buffer.isBuffer(chunk) && - 'string' !== typeof chunk && - chunk !== null && - chunk !== undefined && - !state.objectMode) { - var er = new TypeError('Invalid non-string/buffer chunk'); - stream.emit('error', er); - process.nextTick(function() { - cb(er); - }); - valid = false; - } - return valid; -} - -Writable.prototype.write = function(chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; - else if (!encoding) - encoding = state.defaultEncoding; - - if (typeof cb !== 'function') - cb = function() {}; - - if (state.ended) - writeAfterEnd(this, state, cb); - else if (validChunk(this, state, chunk, cb)) - ret = writeOrBuffer(this, state, chunk, encoding, cb); - - return ret; -}; - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && - state.decodeStrings !== false && - typeof chunk === 'string') { - chunk = new Buffer(chunk, encoding); - } - return chunk; -} - -// if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, chunk, encoding, cb) { - chunk = decodeChunk(state, chunk, encoding); - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; - var len = state.objectMode ? 1 : chunk.length; - - state.length += len; - - var ret = state.length < state.highWaterMark; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) - state.needDrain = true; - - if (state.writing) - state.buffer.push(new WriteReq(chunk, encoding, cb)); - else - doWrite(stream, state, len, chunk, encoding, cb); - - return ret; -} - -function doWrite(stream, state, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - if (sync) - process.nextTick(function() { - cb(er); - }); - else - cb(er); - - stream._writableState.errorEmitted = true; - stream.emit('error', er); -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - - onwriteStateUpdate(state); - - if (er) - onwriteError(stream, state, sync, er, cb); - else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(stream, state); - - if (!finished && !state.bufferProcessing && state.buffer.length) - clearBuffer(stream, state); - - if (sync) { - process.nextTick(function() { - afterWrite(stream, state, finished, cb); - }); - } else { - afterWrite(stream, state, finished, cb); - } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) - onwriteDrain(stream, state); - cb(); - if (finished) - finishMaybe(stream, state); -} - -// Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} - - -// if there's something in the buffer waiting, then process it -function clearBuffer(stream, state) { - state.bufferProcessing = true; - - for (var c = 0; c < state.buffer.length; c++) { - var entry = state.buffer[c]; - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - - doWrite(stream, state, len, chunk, encoding, cb); - - // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - if (state.writing) { - c++; - break; - } - } - - state.bufferProcessing = false; - if (c < state.buffer.length) - state.buffer = state.buffer.slice(c); - else - state.buffer.length = 0; -} - -Writable.prototype._write = function(chunk, encoding, cb) { - cb(new Error('not implemented')); -}; - -Writable.prototype.end = function(chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (typeof chunk !== 'undefined' && chunk !== null) - this.write(chunk, encoding); - - // ignore unnecessary end() calls. - if (!state.ending && !state.finished) - endWritable(this, state, cb); -}; - - -function needFinish(stream, state) { - return (state.ending && - state.length === 0 && - !state.finished && - !state.writing); -} - -function finishMaybe(stream, state) { - var need = needFinish(stream, state); - if (need) { - state.finished = true; - stream.emit('finish'); - } - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - if (cb) { - if (state.finished) - process.nextTick(cb); - else - stream.once('finish', cb); - } - state.ended = true; -} - -}).call(this,require('_process')) -},{"./_stream_duplex":54,"_process":48,"buffer":35,"core-util-is":59,"inherits":45,"stream":64}],59:[function(require,module,exports){ -(function (Buffer){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -function isBuffer(arg) { - return Buffer.isBuffer(arg); -} -exports.isBuffer = isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} -}).call(this,require("buffer").Buffer) -},{"buffer":35}],60:[function(require,module,exports){ -module.exports = require("./lib/_stream_passthrough.js") - -},{"./lib/_stream_passthrough.js":55}],61:[function(require,module,exports){ -var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify -exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = Stream; -exports.Readable = exports; -exports.Writable = require('./lib/_stream_writable.js'); -exports.Duplex = require('./lib/_stream_duplex.js'); -exports.Transform = require('./lib/_stream_transform.js'); -exports.PassThrough = require('./lib/_stream_passthrough.js'); - -},{"./lib/_stream_duplex.js":54,"./lib/_stream_passthrough.js":55,"./lib/_stream_readable.js":56,"./lib/_stream_transform.js":57,"./lib/_stream_writable.js":58,"stream":64}],62:[function(require,module,exports){ -module.exports = require("./lib/_stream_transform.js") - -},{"./lib/_stream_transform.js":57}],63:[function(require,module,exports){ -module.exports = require("./lib/_stream_writable.js") - -},{"./lib/_stream_writable.js":58}],64:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = Stream; - -var EE = require('events').EventEmitter; -var inherits = require('inherits'); - -inherits(Stream, EE); -Stream.Readable = require('readable-stream/readable.js'); -Stream.Writable = require('readable-stream/writable.js'); -Stream.Duplex = require('readable-stream/duplex.js'); -Stream.Transform = require('readable-stream/transform.js'); -Stream.PassThrough = require('readable-stream/passthrough.js'); - -// Backwards-compat with node 0.4.x -Stream.Stream = Stream; - - - -// old-style streams. Note that the pipe method (the only relevant -// part of this class) is overridden in the Readable class. - -function Stream() { - EE.call(this); -} - -Stream.prototype.pipe = function(dest, options) { - var source = this; - - function ondata(chunk) { - if (dest.writable) { - if (false === dest.write(chunk) && source.pause) { - source.pause(); - } - } - } - - source.on('data', ondata); - - function ondrain() { - if (source.readable && source.resume) { - source.resume(); - } - } - - dest.on('drain', ondrain); - - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once. - if (!dest._isStdio && (!options || options.end !== false)) { - source.on('end', onend); - source.on('close', onclose); - } - - var didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; - - dest.end(); - } - - - function onclose() { - if (didOnEnd) return; - didOnEnd = true; - - if (typeof dest.destroy === 'function') dest.destroy(); - } - - // don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (EE.listenerCount(this, 'error') === 0) { - throw er; // Unhandled stream error in pipe. - } - } - - source.on('error', onerror); - dest.on('error', onerror); - - // remove all the event listeners that were added. - function cleanup() { - source.removeListener('data', ondata); - dest.removeListener('drain', ondrain); - - source.removeListener('end', onend); - source.removeListener('close', onclose); - - source.removeListener('error', onerror); - dest.removeListener('error', onerror); - - source.removeListener('end', cleanup); - source.removeListener('close', cleanup); - - dest.removeListener('close', cleanup); - } - - source.on('end', cleanup); - source.on('close', cleanup); - - dest.on('close', cleanup); - - dest.emit('pipe', source); - - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; -}; - -},{"events":39,"inherits":45,"readable-stream/duplex.js":53,"readable-stream/passthrough.js":60,"readable-stream/readable.js":61,"readable-stream/transform.js":62,"readable-stream/writable.js":63}],65:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var Buffer = require('buffer').Buffer; - -var isBufferEncoding = Buffer.isEncoding - || function(encoding) { - switch (encoding && encoding.toLowerCase()) { - case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; - default: return false; - } - } - - -function assertEncoding(encoding) { - if (encoding && !isBufferEncoding(encoding)) { - throw new Error('Unknown encoding: ' + encoding); - } -} - -// StringDecoder provides an interface for efficiently splitting a series of -// buffers into a series of JS strings without breaking apart multi-byte -// characters. CESU-8 is handled as part of the UTF-8 encoding. -// -// @TODO Handling all encodings inside a single object makes it very difficult -// to reason about this code, so it should be split up in the future. -// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code -// points as used by CESU-8. -var StringDecoder = exports.StringDecoder = function(encoding) { - this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); - assertEncoding(encoding); - switch (this.encoding) { - case 'utf8': - // CESU-8 represents each of Surrogate Pair by 3-bytes - this.surrogateSize = 3; - break; - case 'ucs2': - case 'utf16le': - // UTF-16 represents each of Surrogate Pair by 2-bytes - this.surrogateSize = 2; - this.detectIncompleteChar = utf16DetectIncompleteChar; - break; - case 'base64': - // Base-64 stores 3 bytes in 4 chars, and pads the remainder. - this.surrogateSize = 3; - this.detectIncompleteChar = base64DetectIncompleteChar; - break; - default: - this.write = passThroughWrite; - return; - } - - // Enough space to store all bytes of a single character. UTF-8 needs 4 - // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). - this.charBuffer = new Buffer(6); - // Number of bytes received for the current incomplete multi-byte character. - this.charReceived = 0; - // Number of bytes expected for the current incomplete multi-byte character. - this.charLength = 0; -}; - - -// write decodes the given buffer and returns it as JS string that is -// guaranteed to not contain any partial multi-byte characters. Any partial -// character found at the end of the buffer is buffered up, and will be -// returned when calling write again with the remaining bytes. -// -// Note: Converting a Buffer containing an orphan surrogate to a String -// currently works, but converting a String to a Buffer (via `new Buffer`, or -// Buffer#write) will replace incomplete surrogates with the unicode -// replacement character. See https://codereview.chromium.org/121173009/ . -StringDecoder.prototype.write = function(buffer) { - var charStr = ''; - // if our last write ended with an incomplete multibyte character - while (this.charLength) { - // determine how many remaining bytes this buffer has to offer for this char - var available = (buffer.length >= this.charLength - this.charReceived) ? - this.charLength - this.charReceived : - buffer.length; - - // add the new bytes to the char buffer - buffer.copy(this.charBuffer, this.charReceived, 0, available); - this.charReceived += available; - - if (this.charReceived < this.charLength) { - // still not enough chars in this buffer? wait for more ... - return ''; - } - - // remove bytes belonging to the current character from the buffer - buffer = buffer.slice(available, buffer.length); - - // get the character that was split - charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); - - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - var charCode = charStr.charCodeAt(charStr.length - 1); - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - this.charLength += this.surrogateSize; - charStr = ''; - continue; - } - this.charReceived = this.charLength = 0; - - // if there are no more bytes in this buffer, just emit our char - if (buffer.length === 0) { - return charStr; - } - break; - } - - // determine and set charLength / charReceived - this.detectIncompleteChar(buffer); - - var end = buffer.length; - if (this.charLength) { - // buffer the incomplete character bytes we got - buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); - end -= this.charReceived; - } - - charStr += buffer.toString(this.encoding, 0, end); - - var end = charStr.length - 1; - var charCode = charStr.charCodeAt(end); - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - var size = this.surrogateSize; - this.charLength += size; - this.charReceived += size; - this.charBuffer.copy(this.charBuffer, size, 0, size); - buffer.copy(this.charBuffer, 0, 0, size); - return charStr.substring(0, end); - } - - // or just emit the charStr - return charStr; -}; - -// detectIncompleteChar determines if there is an incomplete UTF-8 character at -// the end of the given buffer. If so, it sets this.charLength to the byte -// length that character, and sets this.charReceived to the number of bytes -// that are available for this character. -StringDecoder.prototype.detectIncompleteChar = function(buffer) { - // determine how many bytes we have to check at the end of this buffer - var i = (buffer.length >= 3) ? 3 : buffer.length; - - // Figure out if one of the last i bytes of our buffer announces an - // incomplete char. - for (; i > 0; i--) { - var c = buffer[buffer.length - i]; - - // See http://en.wikipedia.org/wiki/UTF-8#Description - - // 110XXXXX - if (i == 1 && c >> 5 == 0x06) { - this.charLength = 2; - break; - } - - // 1110XXXX - if (i <= 2 && c >> 4 == 0x0E) { - this.charLength = 3; - break; - } - - // 11110XXX - if (i <= 3 && c >> 3 == 0x1E) { - this.charLength = 4; - break; - } - } - this.charReceived = i; -}; - -StringDecoder.prototype.end = function(buffer) { - var res = ''; - if (buffer && buffer.length) - res = this.write(buffer); - - if (this.charReceived) { - var cr = this.charReceived; - var buf = this.charBuffer; - var enc = this.encoding; - res += buf.slice(0, cr).toString(enc); - } - - return res; -}; - -function passThroughWrite(buffer) { - return buffer.toString(this.encoding); -} - -function utf16DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 2; - this.charLength = this.charReceived ? 2 : 0; -} - -function base64DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 3; - this.charLength = this.charReceived ? 3 : 0; -} - -},{"buffer":35}],66:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var punycode = require('punycode'); - -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; - -exports.Url = Url; - -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; -} - -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = require('querystring'); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; -} - -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a puny coded representation of "domain". - // It only converts the part of the domain name that - // has non ASCII characters. I.e. it dosent matter if - // you call it with a domain that already is in ASCII. - var domainArray = this.hostname.split('.'); - var newOut = []; - for (var i = 0; i < domainArray.length; ++i) { - var s = domainArray[i]; - newOut.push(s.match(/[^A-Za-z0-9_-]/) ? - 'xn--' + punycode.encode(s) : s); - } - this.hostname = newOut.join('.'); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - Object.keys(this).forEach(function(k) { - result[k] = this[k]; - }, this); - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - Object.keys(relative).forEach(function(k) { - if (k !== 'protocol') - result[k] = relative[k]; - }); - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - Object.keys(relative).forEach(function(k) { - result[k] = relative[k]; - }); - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host) && (last === '.' || last === '..') || - last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last == '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - -function isString(arg) { - return typeof arg === "string"; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isNull(arg) { - return arg === null; -} -function isNullOrUndefined(arg) { - return arg == null; -} - -},{"punycode":49,"querystring":52}],67:[function(require,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],68:[function(require,module,exports){ -(function (process,global){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; - } else { - str += ' ' + inspect(x); - } - } - return str; -}; - - -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } - - if (process.noDeprecation === true) { - return fn; - } - - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } - - return deprecated; -}; - - -var debugs = {}; -var debugEnviron; -exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; - } - } - return debugs[set]; -}; - - -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; - - -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; - -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; - - -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; - - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} - - -function stylizeNoColor(str, styleType) { - return str; -} - - -function arrayToHash(array) { - var hash = {}; - - array.forEach(function(val, idx) { - hash[val] = true; - }); - - return hash; -} - - -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); - - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } - - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } - - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } - - var base = '', array = false, braces = ['{', '}']; - - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } - - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } - - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } - - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } - - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } - - ctx.seen.push(value); - - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - - ctx.seen.pop(); - - return reduceToSingleString(output, base, braces); -} - - -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} - - -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} - - -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} - - -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - - return name + ': ' + str; -} - - -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); - - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } - - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} - - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = require('./support/isBuffer'); - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - - -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); -}; - - -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = require('inherits'); - -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; - -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":67,"_process":48,"inherits":45}]},{},[1]);