From c7d31293d786b734faf6a0c6e9dc9206bbda2718 Mon Sep 17 00:00:00 2001 From: Ilija Ljubicic Date: Tue, 1 Aug 2017 14:15:38 +0200 Subject: [PATCH 1/2] stripped down version to work with pixeltracker --- Gruntfile.js | 1 + core/.npmignore | 2 - core/CHANGELOG | 28 - core/Gruntfile.js | 39 - core/README.md | 132 --- core/index.js | 16 - core/lib/base64.js | 82 -- core/lib/core.js | 687 ------------- core/lib/payload.js | 110 --- core/license.txt | 202 ---- core/package.json | 30 - core/tests/base64.js | 32 - core/tests/core.js | 600 ------------ core/tests/intern.js | 55 -- core/tests/payload.js | 121 --- package.json | 9 +- src/js/forms.js | 177 ---- src/js/in_queue.js | 30 +- src/js/lib/detectors.js | 160 ---- src/js/lib/helpers.js | 46 +- src/js/links.js | 199 ---- src/js/out_queue.js | 221 ++--- src/js/snowplow.js | 10 +- src/js/tracker.js | 2023 +-------------------------------------- 24 files changed, 138 insertions(+), 4874 deletions(-) delete mode 100644 core/.npmignore delete mode 100644 core/CHANGELOG delete mode 100644 core/Gruntfile.js delete mode 100644 core/README.md delete mode 100644 core/index.js delete mode 100644 core/lib/base64.js delete mode 100644 core/lib/core.js delete mode 100644 core/lib/payload.js delete mode 100644 core/license.txt delete mode 100644 core/package.json delete mode 100644 core/tests/base64.js delete mode 100644 core/tests/core.js delete mode 100644 core/tests/intern.js delete mode 100644 core/tests/payload.js delete mode 100644 src/js/forms.js delete mode 100644 src/js/links.js diff --git a/Gruntfile.js b/Gruntfile.js index 6297a611a..6eed360bc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -252,6 +252,7 @@ module.exports = function(grunt) { }); }); + grunt.registerTask('nonmin', 'Build lodash, Browserify, add banner', ['lodash', 'browserify:main', 'concat:deploy']); grunt.registerTask('default', 'Build lodash, Browserify, add banner, and minify', ['lodash', 'browserify:main', 'concat:deploy', 'min:deploy']); grunt.registerTask('publish', 'Upload to S3 and invalidate Cloudfront (full semantic version only)', ['upload_setup', 'lodash', 'browserify:main', 'concat:deploy', 'min:deploy', 's3:not_pinned', 'cloudfront:not_pinned']); grunt.registerTask('publish-pinned', 'Upload to S3 and invalidate Cloudfront (full semantic version and semantic major version)', ['upload_setup', 'lodash', 'browserify:main', 'concat:deploy', 'min:deploy', 's3', 'cloudfront']); diff --git a/core/.npmignore b/core/.npmignore deleted file mode 100644 index 8f33598ed..000000000 --- a/core/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -tests/ -Gruntfile.js diff --git a/core/CHANGELOG b/core/CHANGELOG deleted file mode 100644 index 465266856..000000000 --- a/core/CHANGELOG +++ /dev/null @@ -1,28 +0,0 @@ -Version 0.4.0 (2014-12-03) --------------------------- -Updated contexts schema to 1-0-1 (#292) -Added ability to send an empty contexts array (#296) - -Version 0.3.0 (2014-11-04) --------------------------- -Applied callback to the Payload for an event rather than the event dictionary (#259) -Added page scroll parameters to trackPagePing (#257) -Added social tracking (#258) -Added trackAddToCart and trackRemoveFromCart methods (#260) -Added trackFormChange and trackFormSubmission methods (#261) -Added trackSiteSearch method (#263) -Added content field to trackLinkClick (#262) - -Version 0.2.0 (2014-08-07) --------------------------- -Added UUID to payload (#244) -Added automatic timestamp generation (#243) -Added setter methods (#242) -Added timestamp parameter to tracker methods (#240) -Added dependendencies field to package.json (#239) -Added npm button to README (#238) -Updated README (#237) - -Version 0.1.0 (2014-08-01) --------------------------- -Initial release diff --git a/core/Gruntfile.js b/core/Gruntfile.js deleted file mode 100644 index c92a76bbb..000000000 --- a/core/Gruntfile.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -* JavaScript tracker core for Snowplow: Gruntfile.js -* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -/*global module:false*/ -module.exports = function(grunt) { - - grunt.initConfig({ - - intern: { - nonfunctional: { - options: { - runType: 'client', - config: 'tests/intern.js', - suites: [ - 'tests/base64.js', - 'tests/payload.js', - 'tests/core.js' - ] - } - } - } - }); - - grunt.loadNpmTasks('intern'); - - grunt.registerTask('default', 'Run tests', ['intern']); -} diff --git a/core/README.md b/core/README.md deleted file mode 100644 index 912415f84..000000000 --- a/core/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# Snowplow JavaScript Tracker Core [![npm version][npm-image]][npm-url] - -Core module to be used by all Snowplow JavaScript trackers. - -## Installation - -With npm: - -```bash -npm install snowplow-tracker-core -``` - -## Example - -```js -var core = require('snowplow-tracker-core'); - -// Create an instance with base 64 encoding set to false (it defaults to true) -var coreInstance = core(false); - -// Add a name-value pair to all payloads -coreInstance.addPayloadPair('vid', 2); - -// Add each name-value pair in a dictionary to all payloads -coreInstance.addPayloadDict({ - 'ds': '1160x620', - 'fp': 4070134789 -}); - -// Add name-value pairs to all payloads using convenience methods -coreInstance.setTrackerVersion('js-3.0.0'); -coreInstance.setPlatform('web'); -coreInstance.setUserId('user-321'); -coreInstance.setColorDepth(24); -coreInstance.setViewport(600, 400); - -// Track a page view with URL and title -var pageViewPayload = coreInstance.trackPageView('http://www.example.com', 'landing page'); - -console.log(pageViewPayload); -/* -{ - 'e': 'pv', - 'url': 'http://www.example.com', - 'page': 'landing page', - 'uid': 'user-321', - 'vd': 2, - 'ds': '1160x620', - 'fp': 4070134789 - 'tv': 'js-3.0.0', - 'p': 'web', - 'cd': 24, - 'vp': '600x400', - 'dtm': 1406879959702, // timestamp - 'eid': '0718a85a-45dc-4f71-a949-27870442ed7d' // UUID -} -*/ - -// Stop automatically adding tv, p, and dtm to the payload -coreInstance.resetPayloadPairs(); - -// Track an unstructured event -var unstructEventPayload = coreInstance.trackUnstructEvent({ - 'schema': 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-0', - 'data': { - 'targetUrl': 'http://www.destination.com', - 'elementId': 'bannerLink' - } -}); - -console.log(unstructEventPayload); -/* -{ - 'e': 'ue', - 'ue_pr': { - 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_even/jsonschema/1-0-0', - 'data': { - 'schema': 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-0', - 'data': { - 'targetUrl': 'http://www.destination.com', - 'elementId': 'bannerLink' - } - } - }, - 'dtm': 1406879973439, - 'eid': '956c6670-cbf6-460b-9f96-143e0320fdf6' -} -*/ -``` - -## Other features - -Core instances can be initialized with two parameters. The first is a boolean and determines whether custom contexts and unstructured events will be base 64 encoded. The second is an optional callback function which gets applied to every payload created by the instance. - -```js -var coreInstance = core(true, console.log); -``` - -The above example would base 64 encode all unstructured events and custom contexts and would log each payload to the console. - -Use the `setBase64Encoding` method to turn base 64 encoding on or off after initializing a core instance: - -```js -var core = require('snowplow-tracker-core'); - -var coreInstance = core(); // Base 64 encoding on by default - -coreInstance.setBase64Encoding(false); // Base 64 encoding is now off -``` - -## Documentation - -For more information on the Snowplow JavaScript Tracker Core's API, view its [wiki page][wiki]. - -## Copyright and license - -The Snowplow JavaScript Tracker Core is copyright 2014 Snowplow Analytics Ltd. - -Licensed under the [Apache License, Version 2.0][apache-license] (the "License"); -you may not use this software except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -[apache-license]: http://www.apache.org/licenses/LICENSE-2.0 - -[npm-url]: http://badge.fury.io/js/snowplow-tracker-core -[npm-image]: https://badge.fury.io/js/snowplow-tracker-core.svg -[wiki]: https://github.com/snowplow/snowplow/wiki/Javascript-Tracker-Core diff --git a/core/index.js b/core/index.js deleted file mode 100644 index 78d087dfb..000000000 --- a/core/index.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: index.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -module.exports = require('./lib/core'); diff --git a/core/lib/base64.js b/core/lib/base64.js deleted file mode 100644 index 715c0e63b..000000000 --- a/core/lib/base64.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io) - * and Contributors (http://phpjs.org/authors) - * - * 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() { - - var object = typeof exports !== 'undefined' ? exports : this; // For eventual node.js environment support - - function base64_encode(data) { - // discuss at: http://phpjs.org/functions/base64_encode/ - // original by: Tyler Akins (http://rumkin.com) - // improved by: Bayron Guevara - // improved by: Thunder.m - // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // improved by: Rafał Kukawski (http://kukawski.pl) - // bugfixed by: Pellentesque Malesuada - // example 1: base64_encode('Kevin van Zonneveld'); - // returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' - // example 2: base64_encode('a'); - // returns 2: 'YQ==' - // example 3: base64_encode('✓ à la mode'); - // returns 3: '4pyTIMOgIGxhIG1vZGU=' - - var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, - ac = 0, - enc = '', - tmp_arr = []; - - if (!data) { - return data; - } - - data = unescape(encodeURIComponent(data)); - - do { - // pack three octets into four hexets - o1 = data.charCodeAt(i++); - o2 = data.charCodeAt(i++); - o3 = data.charCodeAt(i++); - - bits = o1 << 16 | o2 << 8 | o3; - - h1 = bits >> 18 & 0x3f; - h2 = bits >> 12 & 0x3f; - h3 = bits >> 6 & 0x3f; - h4 = bits & 0x3f; - - // use hexets to index into b64, and append result to encoded string - tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); - } while (i < data.length); - - enc = tmp_arr.join(''); - - var r = data.length % 3; - - return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); - } - - object.base64encode = base64_encode; - -}()); diff --git a/core/lib/core.js b/core/lib/core.js deleted file mode 100644 index dafc77155..000000000 --- a/core/lib/core.js +++ /dev/null @@ -1,687 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: core.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -var payload = require('./payload.js'); -var uuid = require('uuid'); - -/** - * Create a tracker core object - * - * @param boolean base64 Whether to base 64 encode contexts and unstructured event JSONs - * @param callback function Function applied to every payload dictionary object - * @return object Tracker core - */ -function trackerCore(base64, callback) { - - // base 64 encoding should default to true - if (typeof base64 === 'undefined') { - base64 = true; - } - - // Dictionary of key-value pairs which get added to every payload, e.g. tracker version - var payloadPairs = {}; - - /** - * Set a persistent key-value pair to be added to every payload - * - * @param string key Field name - * @param string value Field value - */ - function addPayloadPair(key, value) { - payloadPairs[key] = value; - } - - /** - * Returns a copy of a JSON with undefined and null properties removed - * - * @param object eventJson JSON to clean - * @param object exemptFields Set of fields which should not be removed even if empty - * @return object A cleaned copy of eventJson - */ - function removeEmptyProperties(eventJson, exemptFields) { - var ret = {}; - exemptFields = exemptFields || {}; - for (var k in eventJson) { - if (exemptFields[k] || (eventJson[k] !== null && typeof eventJson[k] !== 'undefined')) { - ret[k] = eventJson[k]; - } - } - return ret; - } - - /** - * Wraps an array of custom contexts in a self-describing JSON - * - * @param array contexts Array of custom context self-describing JSONs - * @return object Outer JSON - */ - function completeContexts(contexts) { - if (contexts) { - return { - schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-1', - data: contexts - }; - } - } - - /** - * Gets called by every trackXXX method - * Adds context and payloadPairs name-value pairs to the payload - * Applies the callback to the built payload - * - * @param sb object Payload - * @param array contexts Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload after the callback is applied - */ - function track(sb, context, tstamp) { - sb.addDict(payloadPairs); - sb.add('eid', uuid.v4()); - sb.add('dtm', tstamp || new Date().getTime()); - if (context) { - sb.addJson('cx', 'co', completeContexts(context)); - } - - if (typeof callback === 'function') { - callback(sb); - } - - return sb; - } - - /** - * Log an unstructured event - * - * @param object eventJson Contains the properties and schema location for the event - * @param array context Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - function trackUnstructEvent(properties, context, tstamp) { - var sb = payload.payloadBuilder(base64); - var ueJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', - data: properties - }; - - sb.add('e', 'ue'); - sb.addJson('ue_px', 'ue_pr', ueJson); - - return track(sb, context, tstamp); - } - - return { - - /** - * Turn base 64 encoding on or off - * - * @param boolean encode key Field name - */ - setBase64Encoding: function (encode) { - base64 = encode; - }, - - addPayloadPair: addPayloadPair, - - /** - * Merges a dictionary into payloadPairs - * - * @param object dict Dictionary to add - */ - addPayloadDict: function (dict) { - for (var key in dict) { - if (dict.hasOwnProperty(key)) { - payloadPairs[key] = dict[key]; - } - } - }, - - /** - * Replace payloadPairs with a new dictionary - * - * @param object dict New dictionary - */ - resetPayloadPairs: function (dict) { - payloadPairs = payload.isJson(dict) ? dict : {}; - }, - - /** - * Set the tracker version - * - * @param string version - */ - setTrackerVersion: function (version) { - addPayloadPair('tv', version); - }, - - /** - * Set the tracker namespace - * - * @param string name - */ - setTrackerNamespace: function (name) { - addPayloadPair('tna', name); - }, - - /** - * Set the application ID - * - * @param string appId - */ - setAppId: function (appId) { - addPayloadPair('aid', appId); - }, - - /** - * Set the platform - * - * @param string value - */ - setPlatform: function (value) { - addPayloadPair('p', value); - }, - - /** - * Set the user ID - * - * @param string userId - */ - setUserId: function (userId) { - addPayloadPair('uid', userId); - }, - - /** - * Set the screen resolution - * - * @param number width - * @param number height - */ - setScreenResolution: function (width, height) { - addPayloadPair('res', width + 'x' + height); - }, - - /** - * Set the viewport dimensions - * - * @param number width - * @param number height - */ - setViewport: function (width, height) { - addPayloadPair('vp', width + 'x' + height); - }, - - /** - * Set the color depth - * - * @param number depth - */ - setColorDepth: function (depth) { - addPayloadPair('cd', depth); - }, - - /** - * Set the timezone - * - * @param string timezone - */ - setTimezone: function (timezone) { - addPayloadPair('tz', timezone); - }, - - /** - * Set the language - * - * @param string lang - */ - setLang: function (lang) { - addPayloadPair('lang', lang); - }, - - /** - * Set the IP address - * - * @param string appId - */ - setIpAddress: function (ip) { - addPayloadPair('ip', ip); - }, - - trackUnstructEvent: trackUnstructEvent, - - /** - * Log the page view / visit - * - * @param string customTitle The user-defined page title to attach to this page view - * @param array context Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackPageView: function (pageUrl, pageTitle, referrer, context, tstamp) { - var sb = payload.payloadBuilder(base64); - sb.add('e', 'pv'); // 'pv' for Page View - sb.add('url', pageUrl); - sb.add('page', pageTitle); - sb.add('refr', referrer); - - return track(sb, context, tstamp); - }, - /** - * Log that a user is still viewing a given page - * by sending a page ping. - * - * @param string pageTitle The page title to attach to this page ping - * @param minxoffset Minimum page x offset seen in the last ping period - * @param maxXOffset Maximum page x offset seen in the last ping period - * @param minYOffset Minimum page y offset seen in the last ping period - * @param maxYOffset Maximum page y offset seen in the last ping period - * @param array context Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackPagePing: function (pageUrl, pageTitle, referrer, minXOffset, maxXOffset, minYOffset, maxYOffset, context, tstamp) { - var sb = payload.payloadBuilder(base64); - sb.add('e', 'pp'); // 'pp' for Page Ping - sb.add('url', pageUrl); - sb.add('page', pageTitle); - sb.add('refr', referrer); - sb.add('pp_mix', minXOffset); - sb.add('pp_max', maxXOffset); - sb.add('pp_miy', minYOffset); - sb.add('pp_may', maxYOffset); - - return track(sb, context, tstamp); - }, - /** - * Track a structured event - * - * @param string category The name you supply for the group of objects you want to track - * @param string action A string that is uniquely paired with each category, and commonly used to define the type of user interaction for the web object - * @param string label (optional) An optional string to provide additional dimensions to the event data - * @param string property (optional) Describes the object or the action performed on it, e.g. quantity of item added to basket - * @param int|float|string value (optional) An integer that you can use to provide numerical data about the user event - * @param array Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackStructEvent: function (category, action, label, property, value, context, tstamp) { - var sb = payload.payloadBuilder(base64); - sb.add('e', 'se'); // 'se' for Structured Event - sb.add('se_ca', category); - sb.add('se_ac', action); - sb.add('se_la', label); - sb.add('se_pr', property); - sb.add('se_va', value); - - return track(sb, context, tstamp); - }, - - /** - * Track an ecommerce transaction - * - * @param string orderId Required. Internal unique order id number for this transaction. - * @param string affiliation Optional. Partner or store affiliation. - * @param string total Required. Total amount of the transaction. - * @param string tax Optional. Tax amount of the transaction. - * @param string shipping Optional. Shipping charge for the transaction. - * @param string city Optional. City to associate with transaction. - * @param string state Optional. State to associate with transaction. - * @param string country Optional. Country to associate with transaction. - * @param string currency Optional. Currency to associate with this transaction. - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackEcommerceTransaction: function (orderId, affiliation, totalValue, taxValue, shipping, city, state, country, currency, context, tstamp) { - var sb = payload.payloadBuilder(base64); - sb.add('e', 'tr'); // 'tr' for Transaction - sb.add("tr_id", orderId); - sb.add("tr_af", affiliation); - sb.add("tr_tt", totalValue); - sb.add("tr_tx", taxValue); - sb.add("tr_sh", shipping); - sb.add("tr_ci", city); - sb.add("tr_st", state); - sb.add("tr_co", country); - sb.add("tr_cu", currency); - - return track(sb, context, tstamp); - }, - - /** - * Track an ecommerce transaction item - * - * @param string orderId Required Order ID of the transaction to associate with item. - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string price Required. Product price. - * @param string quantity Required. Purchase quantity. - * @param string currency Optional. Product price currency. - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackEcommerceTransactionItem: function (orderId, sku, name, category, price, quantity, currency, context, tstamp) { - var sb = payload.payloadBuilder(base64); - sb.add("e", "ti"); // 'tr' for Transaction Item - sb.add("ti_id", orderId); - sb.add("ti_sk", sku); - sb.add("ti_nm", name); - sb.add("ti_ca", category); - sb.add("ti_pr", price); - sb.add("ti_qu", quantity); - sb.add("ti_cu", currency); - - return track(sb, context, tstamp); - }, - - /** - * Track a screen view unstructured event - * - * @param string name The name of the screen - * @param string id The ID of the screen - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackScreenView: function (name, id, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0', - data: removeEmptyProperties({ - name: name, - id: id - }) - }, context, tstamp); - }, - - /** - * Log the link or click with the server - * - * @param string targetUrl - * @param string elementId - * @param array elementClasses - * @param string elementTarget - * @param string elementContent innerHTML of the link - * @param array context Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackLinkClick: function (targetUrl, elementId, elementClasses, elementTarget, elementContent, context, tstamp) { - var eventJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', - data: removeEmptyProperties({ - targetUrl: targetUrl, - elementId: elementId, - elementClasses: elementClasses, - elementTarget: elementTarget, - elementContent: elementContent - }), - }; - - return trackUnstructEvent(eventJson, context, tstamp); - }, - - /** - * Track an ad being served - * - * @param string impressionId Identifier for a particular ad impression - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param number cost Cost - * @param string bannerId Identifier for the ad banner displayed - * @param string zoneId Identifier for the ad zone - * @param string advertiserId Identifier for the advertiser - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param array Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackAdImpression: function(impressionId, costModel, cost, targetUrl, bannerId, zoneId, advertiserId, campaignId, context, tstamp) { - var eventJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0', - data: removeEmptyProperties({ - impressionId: impressionId, - costModel: costModel, - cost: cost, - targetUrl: targetUrl, - bannerId: bannerId, - zoneId: zoneId, - advertiserId: advertiserId, - campaignId: campaignId - }) - }; - - return trackUnstructEvent(eventJson, context, tstamp); - }, - - /** - * Track an ad being clicked - * - * @param string clickId Identifier for the ad click - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param number cost Cost - * @param string targetUrl (required) The link's target URL - * @param string bannerId Identifier for the ad banner displayed - * @param string zoneId Identifier for the ad zone - * @param string impressionId Identifier for a particular ad impression - * @param string advertiserId Identifier for the advertiser - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param array Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackAdClick: function (targetUrl, clickId, costModel, cost, bannerId, zoneId, impressionId, advertiserId, campaignId, context, tstamp) { - var eventJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_click/jsonschema/1-0-0', - data: removeEmptyProperties({ - targetUrl: targetUrl, - clickId: clickId, - costModel: costModel, - cost: cost, - bannerId: bannerId, - zoneId: zoneId, - impressionId: impressionId, - advertiserId: advertiserId, - campaignId: campaignId - }) - }; - - return trackUnstructEvent(eventJson, context, tstamp); - }, - - /** - * Track an ad conversion event - * - * @param string conversionId Identifier for the ad conversion event - * @param number cost Cost - * @param string category The name you supply for the group of objects you want to track - * @param string action A string that is uniquely paired with each category - * @param string property Describes the object of the conversion or the action performed on it - * @param number initialValue Revenue attributable to the conversion at time of conversion - * @param string advertiserId Identifier for the advertiser - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param array Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackAdConversion: function (conversionId, costModel, cost, category, action, property, initialValue, advertiserId, campaignId, context, tstamp) { - var eventJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_conversion/jsonschema/1-0-0', - data: removeEmptyProperties({ - conversionId: conversionId, - costModel: costModel, - cost: cost, - category: category, - action: action, - property: property, - initialValue: initialValue, - advertiserId: advertiserId, - campaignId: campaignId - }) - }; - - return trackUnstructEvent(eventJson, context, tstamp); - }, - - /** - * Track a social event - * - * @param string action Social action performed - * @param string network Social network - * @param string target Object of the social action e.g. the video liked, the tweet retweeted - * @param array Custom contexts relating to the event - * @param number tstamp Timestamp of the event - * @return object Payload - */ - trackSocialInteraction: function (action, network, target, context, tstamp) { - var eventJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/social_interaction/jsonschema/1-0-0', - data: removeEmptyProperties({ - action: action, - network: network, - target: target - }) - }; - - return trackUnstructEvent(eventJson, context, tstamp); - }, - - /** - * Track an add-to-cart event - * - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string unitPrice Optional. Product price. - * @param string quantity Required. Quantity added. - * @param string currency Optional. Product price currency. - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackAddToCart: function (sku, name, category, unitPrice, quantity, currency, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/add_to_cart/jsonschema/1-0-0', - data: removeEmptyProperties({ - sku: sku, - name: name, - category: category, - unitPrice: unitPrice, - quantity: quantity, - currency: currency - }) - }, context, tstamp); - }, - - /** - * Track a remove-from-cart event - * - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string unitPrice Optional. Product price. - * @param string quantity Required. Quantity removed. - * @param string currency Optional. Product price currency. - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackRemoveFromCart: function (sku, name, category, unitPrice, quantity, currency, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/remove_from_cart/jsonschema/1-0-0', - data: removeEmptyProperties({ - sku: sku, - name: name, - category: category, - unitPrice: unitPrice, - quantity: quantity, - currency: currency - }) - }, context, tstamp); - }, - - /** - * Track the value of a form field changing - * - * @param string formId The parent form ID - * @param string elementId ID of the changed element - * @param string nodeName "INPUT", "TEXTAREA", or "SELECT" - * @param string type Type of the changed element if its type is "INPUT" - * @param array elementClasses List of classes of the changed element - * @param string value The new value of the changed element - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackFormChange: function(formId, elementId, nodeName, type, elementClasses, value, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', - data: removeEmptyProperties({ - formId: formId, - elementId: elementId, - nodeName: nodeName, - type: type, - elementClasses: elementClasses, - value: value - }, {'value': true}) - }, context, tstamp); - }, - - /** - * Track a form submission event - * - * @param string formId ID of the form - * @param array formClasses Classes of the form - * @param array elements Mutable elements within the form - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackFormSubmission: function(formId, formClasses, elements, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0', - data: removeEmptyProperties({ - formId: formId, - formClasses: formClasses, - elements: elements - }) - }, context, tstamp); - }, - - /** - * Track an internal search event - * - * @param array terms Search terms - * @param object filters Search filters - * @param totalResults Number of results - * @param pageResults Number of results displayed on page - * @param array context Optional. Context relating to the event. - * @param number tstamp Optional. Timestamp of the event - * @return object Payload - */ - trackSiteSearch: function(terms, filters, totalResults, pageResults, context, tstamp) { - return trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/site_search/jsonschema/1-0-0', - data: removeEmptyProperties({ - terms: terms, - filters: filters, - totalResults: totalResults, - pageResults: pageResults - }) - }, context, tstamp); - } - }; -}; - -module.exports = trackerCore; diff --git a/core/lib/payload.js b/core/lib/payload.js deleted file mode 100644 index 7f1b1fc17..000000000 --- a/core/lib/payload.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: payload.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -;(function() { - - var - json2 = require('JSON'), - base64 = require('./base64'), - - object = typeof exports !== 'undefined' ? exports : this; - - /* - * Bas64 encode data with URL and Filename Safe Alphabet (base64url) - * - * See: http://tools.ietf.org/html/rfc4648#page-7 - */ - function base64urlencode(data) { - if (!data) { - return data; - } - - var enc = base64.base64encode(data); - return enc.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); - } - - /* - * Is property a JSON? - */ - object.isJson = function (property) { - return (typeof property !== 'undefined' && property !== null && - (property.constructor === {}.constructor || property.constructor === [].constructor)); - }; - - /* - * Is property a non-empty JSON? - */ - object.isNonEmptyJson = function (property) { - if (!object.isJson(property)) { - return false; - } - for (var key in property) { - if (property.hasOwnProperty(key)) { - return true; - } - } - return false; - } - - /** - * A helper to build a Snowplow request string from an - * an optional initial value plus a set of individual - * name-value pairs, provided using the add method. - * - * @param boolean base64Encode Whether or not JSONs should be - * Base64-URL-safe-encoded - * - * @return object The request string builder, with add, addRaw and build methods - */ - object.payloadBuilder = function (base64Encode) { - var dict = {}; - - var add = function (key, value) { - if (value !== undefined && value !== null && value !== '') { - dict[key] = value; - } - }; - - var addDict = function (dict) { - for (var key in dict) { - if (dict.hasOwnProperty(key)) { - add(key, dict[key]); - } - } - }; - - var addJson = function (keyIfEncoded, keyIfNotEncoded, json) { - - if (object.isNonEmptyJson(json)) { - var str = json2.stringify(json); - if (base64Encode) { - add(keyIfEncoded, base64urlencode(str)); - } else { - add(keyIfNotEncoded, str); - } - } - }; - - return { - add: add, - addDict: addDict, - addJson: addJson, - build: function () { - return dict; - } - }; - }; - -}()); diff --git a/core/license.txt b/core/license.txt deleted file mode 100644 index 7a4a3ea24..000000000 --- a/core/license.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/core/package.json b/core/package.json deleted file mode 100644 index a26be1498..000000000 --- a/core/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "snowplow-tracker-core", - "version": "0.4.0", - "devDependencies": { - "grunt": "^0.4.5", - "intern": "^2.0.1" - }, - "contributors": [ - "Alex Dean", - "Simon Andersson", - "Fred Blundun" - ], - "description": "Core functionality for the Snowplow JavaScript trackers (browser JavaScript; Node.js; Segment.io server-side)", - "repository": { - "type": "git", - "url": "https://github.com/snowplow/snowplow-javascript-tracker.git" - }, - "bugs": "https://github.com/snowplow/snowplow-javascript-tracker/issues", - "keywords": [ - "tracking", - "web analytics", - "events", - "open source" - ], - "license": "Apache-2.0", - "dependencies": { - "JSON": "^1.0.0", - "uuid": "^1.4.1" - } -} diff --git a/core/tests/base64.js b/core/tests/base64.js deleted file mode 100644 index 47673fc15..000000000 --- a/core/tests/base64.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: tests/base64.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -define([ - "intern!object", - "intern/chai!assert", - "intern/dojo/node!../lib/base64.js" -], function (registerSuite, assert, base64) { - - registerSuite({ - name: "Base 64 encoding test", - "Encode a string": function () { - assert.strictEqual(base64.base64encode('my_string'), 'bXlfc3RyaW5n', 'Base64-encode a string'); - }, - - "Encode a string containing special characters": function () { - assert.strictEqual(base64.base64encode('™®字'), '4oSiwq7lrZc=', 'Base64-encode a containing TM, Registered Trademark, and Chinese characters'); - } - }); -}); diff --git a/core/tests/core.js b/core/tests/core.js deleted file mode 100644 index f680e7682..000000000 --- a/core/tests/core.js +++ /dev/null @@ -1,600 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: tests/integration.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -define([ - "intern!object", - "intern/chai!assert", - "intern/dojo/node!../lib/core.js", - "intern/dojo/node!JSON" -], function (registerSuite, assert, core, JSON) { - - var unstructEventSchema = 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0'; - var tracker = core(false); - - function compare(result, expected, message) { - result = result.build(); - assert.ok(result['eid'], 'A UUID should be attached to all events'); - delete result['eid']; - assert.ok(result['dtm'], 'A timestamp should be attached to all events'); - delete result['dtm']; - assert.deepEqual(result, expected, message); - } - - registerSuite({ - name: "Tracking events", - "Track a page view": function () { - var url = 'http://www.example.com'; - var page = 'title page'; - var expected = { - e: 'pv', - url: url, - page: page - }; - compare(tracker.trackPageView(url, page), expected, 'A page view should be tracked correctly'); - }, - - "Track a page ping": function () { - var url = 'http://www.example.com'; - var referer = 'http://www.google.com'; - var expected = { - e: 'pp', - url: url, - refr: referer, - pp_mix: 1, - pp_max: 2, - pp_miy: 3, - pp_may: 4 - }; - - compare(tracker.trackPagePing(url, null, referer, 1, 2, 3, 4), expected, 'A page ping should be tracked correctly'); - }, - - "Track a structured event": function () { - var expected = { - e: 'se', - se_ca: 'cat', - se_ac: 'act', - se_la: 'lab', - se_pr: 'prop', - se_va: 'val' - }; - - compare(tracker.trackStructEvent('cat', 'act', 'lab', 'prop', 'val'), expected, 'A structured event should be tracked correctly'); - }, - - "Track an ecommerce transaction event": function () { - var orderId = 'ak0008'; - var totalValue = 50; - var taxValue = 6; - var shipping = 0; - var city = 'Phoenix'; - var state = 'Arizona'; - var country = 'USA'; - var currency = 'USD'; - var expected = { - e: 'tr', - tr_id: orderId, - tr_tt: totalValue, - tr_tx: taxValue, - tr_sh: shipping, - tr_ci: city, - tr_st: state, - tr_co: country, - tr_cu: currency - }; - - compare(tracker.trackEcommerceTransaction(orderId, null, totalValue, taxValue, shipping, city, state, country, currency), expected, 'A transaction event should be tracked correctly'); - }, - - "Track an ecommerce transaction item event": function () { - var orderId = 'ak0008'; - var sku = '4q345'; - var price = 17; - var quantity = 2; - var name = 'red shoes'; - var category = 'clothing'; - var currency = 'USD'; - var expected = { - e: 'ti', - ti_id: orderId, - ti_sk: sku, - ti_nm: name, - ti_ca: category, - ti_pr: price, - ti_qu: quantity, - ti_cu: currency - }; - - compare(tracker.trackEcommerceTransactionItem(orderId, sku, name, category, price, quantity, currency), expected, 'A transaction item event should be tracked correctly'); - }, - - "Track an unstructured event": function () { - var inputJson = { - schema: 'iglu:com.acme/user/jsonschema/1-0-1', - data: { - name: 'Eric' - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackUnstructEvent(inputJson), expected, 'An unstructured event should be tracked correctly'); - }, - - "Track a link click": function () { - var targetUrl = 'http://www.example.com'; - var elementId = 'first header'; - var elementClasses = ['header']; - var elementContent = 'link'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', - data: { - targetUrl: targetUrl, - elementId: elementId, - elementClasses: elementClasses, - elementContent: elementContent - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackLinkClick(targetUrl, elementId, elementClasses, null, elementContent), expected, 'A link click should be tracked correctly'); - }, - - "Track a screen view": function () { - var name = 'intro'; - var id = '7398-4352-5345-1950'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0', - data: { - name: name, - id: id - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackScreenView(name, id), expected, 'A screen view should be tracked correctly'); - }, - - "Track an ad impression": function () { - var impressionId = 'a0e8f8780ab3'; - var costModel = 'cpc'; - var cost = 0.5; - var targetUrl = 'http://adsite.com'; - var bannerId = '123'; - var zoneId = 'zone-14'; - var advertiserId = 'ad-company'; - var campaignId = 'campaign-7592'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0', - data: { - impressionId: impressionId, - costModel: costModel, - cost: cost, - targetUrl: targetUrl, - bannerId: bannerId, - zoneId: zoneId, - advertiserId: advertiserId, - campaignId: campaignId - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackAdImpression(impressionId, costModel, cost, targetUrl, bannerId, zoneId, advertiserId, campaignId), expected, 'An ad impression should be tracked correctly'); - }, - - "Track an ad click": function () { - var targetUrl = 'http://adsite.com'; - var clickId = 'click-321'; - var costModel = 'cpc'; - var cost = 0.5; - var bannerId = '123'; - var zoneId = 'zone-14'; - var impressionId = 'a0e8f8780ab3'; - var advertiserId = 'ad-company'; - var campaignId = 'campaign-7592'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_click/jsonschema/1-0-0', - data: { - targetUrl: targetUrl, - clickId: clickId, - costModel: costModel, - cost: cost, - bannerId: bannerId, - zoneId: zoneId, - impressionId: impressionId, - advertiserId: advertiserId, - campaignId: campaignId - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackAdClick(targetUrl, clickId, costModel, cost, bannerId, zoneId, impressionId, advertiserId, campaignId), expected, 'An ad click should be tracked correctly'); - }, - - "Track an ad conversion": function () { - var conversionId = 'conversion-59'; - var costModel = 'cpc'; - var cost = 0.5; - var category = 'cat'; - var action = 'act'; - var property = 'prop'; - var initialValue = 7; - var advertiserId = 'ad-company'; - var campaignId = 'campaign-7592'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/ad_conversion/jsonschema/1-0-0', - data: { - conversionId: conversionId, - costModel: costModel, - cost: cost, - category: category, - action: action, - property: property, - initialValue: initialValue, - advertiserId: advertiserId, - campaignId: campaignId - } - }; - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackAdConversion(conversionId, costModel, cost, category, action, property, initialValue, advertiserId, campaignId), expected, 'An ad conversion should be tracked correctly'); - }, - - "Track a social interaction": function () { - var action = 'like'; - var network = 'facebook'; - var target = 'status-0000345345'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/social_interaction/jsonschema/1-0-0', - data: { - action: action, - network: network, - target: target - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackSocialInteraction(action, network, target), expected); - }, - - - "Track an add-to-cart event": function () { - var sku = '4q345'; - var unitPrice = 17; - var quantity = 2; - var name = 'red shoes'; - var category = 'clothing'; - var currency = 'USD'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/add_to_cart/jsonschema/1-0-0', - data: { - sku: sku, - name: name, - category: category, - unitPrice: unitPrice, - quantity: quantity, - currency: currency - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackAddToCart(sku, name, category, unitPrice, quantity, currency), expected); - }, - - "Track a remove-from-cart event": function () { - var sku = '4q345'; - var unitPrice = 17; - var quantity = 2; - var name = 'red shoes'; - var category = 'clothing'; - var currency = 'USD'; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/remove_from_cart/jsonschema/1-0-0', - data: { - sku: sku, - name: name, - category: category, - unitPrice: unitPrice, - quantity: quantity, - currency: currency - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackRemoveFromCart(sku, name, category, unitPrice, quantity, currency), expected); - }, - - "Track a form change event": function () { - var formId = "parent"; - var elementId = "child"; - var nodeName = "INPUT"; - var type = "text"; - var elementClasses = ["important"]; - var value = "male"; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', - data: { - formId: formId, - elementId: elementId, - nodeName: nodeName, - type: type, - elementClasses: elementClasses, - value: value - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackFormChange(formId, elementId, nodeName, type, elementClasses, value), expected); - }, - - "Track a form submission event": function () { - var formId = "parent"; - var formClasses = ["formclass"]; - var elements = [{ - name: "gender", - value: "male", - nodeName: "INPUT", - type: "text" - }]; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0', - data: { - formId: formId, - formClasses: formClasses, - elements: elements - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackFormSubmission(formId, formClasses, elements), expected); - }, - - "Track a site seach event": function () { - var terms = ["javascript", "development"]; - var filters = { - "safeSearch": true, - "category": "books" - }; - var totalResults = 35; - var pageResults = 10; - - var inputJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/site_search/jsonschema/1-0-0', - data: { - terms: terms, - filters: filters, - totalResults: totalResults, - pageResults: pageResults - } - }; - - var expected = { - e: 'ue', - ue_pr: JSON.stringify({ - schema: unstructEventSchema, - data: inputJson - }) - }; - - compare(tracker.trackSiteSearch(terms, filters, totalResults, pageResults), expected); - }, - - "Track a page view with custom context": function () { - var url = 'http://www.example.com'; - var page = 'title page'; - var inputContext = [{ - schema: 'iglu:com.acme/user/jsonschema/1-0-0', - data: { - userType: 'tester', - userName: 'Jon' - } - }]; - var expected = { - e: 'pv', - url: url, - page: page, - co: JSON.stringify({ - schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-1', - data: inputContext - }) - }; - compare(tracker.trackPageView(url, page, null, inputContext), expected, 'A custom context should be attached correctly'); - }, - - "Track a page view with a timestamp": function () { - var tstamp = 1000000000000; - - assert.strictEqual(tracker.trackPageView('http://www.example.com', null, null, null, tstamp).build()['dtm'], tstamp, 'A timestamp should be attached correctly'); - }, - - "Add individual name-value pairs to the payload": function () { - var tracker = core(false); - var url = 'http://www.example.com'; - var expected = { - e: 'pv', - url: url, - tna: 'cf', - tv: 'js-2.0.0' - }; - tracker.addPayloadPair('tna', 'cf'); - tracker.addPayloadPair('tv', 'js-2.0.0'); - - compare(tracker.trackPageView(url), expected, 'Payload name-value pairs should be set correctly'); - }, - - "Add a dictionary of name-value pairs to the payload": function () { - var tracker = core(false); - var url = 'http://www.example.com'; - var expected = { - e: 'pv', - url: url, - tv: 'js-2.0.0', - tna: 'cf', - aid: 'cf325' - }; - tracker.addPayloadPair('tv', 'js-2.0.0'); - tracker.addPayloadDict({ - tna: 'cf', - aid: 'cf325' - }); - - compare(tracker.trackPageView(url), expected, 'Payload name-value pairs should be set correctly'); - }, - - "Reset payload name-value pairs": function () { - var tracker = core(false); - var url = 'http://www.example.com'; - var expected = { - e: 'pv', - url: url, - tna: 'cf' - }; - tracker.addPayloadPair('tna', 'mistake'); - tracker.resetPayloadPairs({'tna': 'cf'}); - - compare(tracker.trackPageView(url), expected, 'Payload name-value pairs should be reset correctly'); - }, - - "Execute a callback": function () { - var callbackTarget; - var tracker = core(false, function (payload) { - callbackTarget = payload; - }); - var url = 'http://www.example.com'; - var expected = { - e: 'pv', - url: url, - }; - tracker.trackPageView(url); - - compare(callbackTarget, expected, 'The callback should be executed correctly'); - }, - - "Use setter methods": function () { - var tracker = core(false); - tracker.setTrackerVersion('js-3.0.0'); - tracker.setTrackerNamespace('cf1'); - tracker.setAppId('my-app'); - tracker.setPlatform('web'); - tracker.setUserId('jacob'); - tracker.setScreenResolution(400, 200); - tracker.setViewport(500, 800); - tracker.setColorDepth(24); - tracker.setTimezone('Europe London'); - tracker.setIpAddress('37.151.33.154'); - var url = 'http://www.example.com'; - var page = 'title page'; - var expected = { - e: 'pv', - url: url, - page: page, - tna: 'cf1', - tv: 'js-3.0.0', - aid: 'my-app', - p: 'web', - uid: 'jacob', - res: '400x200', - vp: '500x800', - cd: 24, - tz: 'Europe London', - ip: '37.151.33.154' - }; - - compare(tracker.trackPageView(url, page), expected, 'setXXX methods should work correctly'); - }, - - }); - -}); diff --git a/core/tests/intern.js b/core/tests/intern.js deleted file mode 100644 index 61fb4d3ad..000000000 --- a/core/tests/intern.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * JavaScript tracker core for Snowplow: tests/intern.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -define({ - - proxyPort: 9000, - proxyUrl: 'http://localhost:9000/', - - capabilities: { - 'selenium-version': '2.39.0', - 'build': 'process.env.TRAVIS_JOB_ID' - }, - - environments: [ - { browserName: 'internet explorer', version: '11', platform: 'Windows 8.1' }, - { browserName: 'internet explorer', version: '10', platform: 'Windows 8' }, - { browserName: 'internet explorer', version: '9', platform: 'Windows 7' }, - { browserName: 'firefox', version: '27', platform: [ 'OS X 10.6', 'Windows 7', 'Linux' ] }, - { browserName: 'chrome', version: '32', platform: [ 'OS X 10.6', 'Windows 7', 'Linux' ] }, - { browserName: 'safari', version: '6', platform: 'OS X 10.8' }, - { browserName: 'safari', version: '7', platform: 'OS X 10.9' } - ], - - maxConcurrency: 3, - useSauceConnect: true, - - // Connection information for the remote WebDriver service. - webdriver: { - host: 'localhost', - port: 4444 - }, - - // Configuration options for the module loader; any AMD configuration options supported by the Dojo loader can be - // used here - loader: {}, - - // Functional test suite(s) to run in each browser once non-functional tests are completed - functionalSuites: [], - - // A regular expression matching URLs to files that should not be included in code coverage analysis - excludeInstrumentation: /^tests\// - -}); diff --git a/core/tests/payload.js b/core/tests/payload.js deleted file mode 100644 index 746a52ba2..000000000 --- a/core/tests/payload.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * JavaScript tracker for Snowplow: tests/payload.js - * - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -define([ - 'intern!object', - 'intern/chai!assert', - 'intern/dojo/node!../lib/payload.js' -], function (registerSuite, assert, payload) { - - - var sampleJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', - data: [ - { - schema: "iglu:com.example_company/page/jsonschema/1-2-1", - data: { - pageType: 'test', - lastUpdated: new Date(2014, 1, 26) - } - }, - { - schema: "iglu:com.example_company/user/jsonschema/2-0-0", - data: { - userType: 'tester' - } - } - ] - }; - - var expectedPayloads = [ - {co: '{"schema":"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0","data":[{"schema":"iglu:com.example_company/page/jsonschema/1-2-1","data":{"pageType":"test","lastUpdated":"2014-02-26T00:00:00.000Z"}},{"schema":"iglu:com.example_company/user/jsonschema/2-0-0","data":{"userType":"tester"}}]}'}, - {cx: 'eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy9jb250ZXh0cy9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6W3sic2NoZW1hIjoiaWdsdTpjb20uZXhhbXBsZV9jb21wYW55L3BhZ2UvanNvbnNjaGVtYS8xLTItMSIsImRhdGEiOnsicGFnZVR5cGUiOiJ0ZXN0IiwibGFzdFVwZGF0ZWQiOiIyMDE0LTAyLTI2VDAwOjAwOjAwLjAwMFoifX0seyJzY2hlbWEiOiJpZ2x1OmNvbS5leGFtcGxlX2NvbXBhbnkvdXNlci9qc29uc2NoZW1hLzItMC0wIiwiZGF0YSI6eyJ1c2VyVHlwZSI6InRlc3RlciJ9fV19'} - ]; - - registerSuite({ - - name: 'Payload test', - - 'Identify a JSON': function () { - var json = { - 'name': 'john', - 'properties': { - 'age': 30, - 'languages': ['English', 'French'] - } - }; - - assert.strictEqual(payload.isJson(json), true, 'JSON should be identified'); - }, - - 'Identify a non-JSON': function () { - var nonJson = function () {}; - - assert.strictEqual(payload.isJson(nonJson), false, 'Non-JSON should be rejected'); - }, - - 'Identify an empty JSON': function () { - var emptyJson = {}; - - assert.strictEqual(payload.isNonEmptyJson(emptyJson), false, '{} should be identified as empty'); - }, - - 'Build a payload': function () { - var sb = payload.payloadBuilder(false); - sb.add('e', 'pv'); - sb.add('tv', 'js-2.0.0'); - - assert.deepEqual(sb.build(), {e: 'pv', tv: 'js-2.0.0'}, 'Individual name-value pairs should be added to the payload'); - }, - - 'Do not add undefined values to a payload': function () { - var sb = payload.payloadBuilder(false); - sb.add('e', undefined); - - assert.deepEqual(sb.build(), {}, 'Undefined values should not be added to the payload'); - }, - - 'Do not add null values to a payload': function () { - var sb = payload.payloadBuilder(false); - sb.add('e', null); - - assert.deepEqual(sb.build(), {}, 'Null values should not be added to the payload'); - }, - - 'Add a dictionary of name-value pairs to the payload': function () { - var sb = payload.payloadBuilder(false); - sb.addDict({ - 'e': 'pv', - 'tv': 'js-2.0.0' - }); - - assert.deepEqual(sb.build(), {e: 'pv', tv: 'js-2.0.0'}, 'A dictionary of name-value pairs should be added to the payload'); - }, - - 'Add a JSON to the payload': function () { - var sb = payload.payloadBuilder(false); - sb.addJson('cx', 'co', sampleJson); - - assert.deepEqual(sb.build(), expectedPayloads[0], 'JSON should be added correctly'); - }, - - 'Add a base 64 encoded JSON to the payload': function () { - var sb = payload.payloadBuilder(true); - sb.addJson('cx', 'co', sampleJson); - - assert.deepEqual(sb.build(), expectedPayloads[1], 'JSON should be encoded correctly'); - } - }); -}); diff --git a/package.json b/package.json index 0a9efb606..e699911aa 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,8 @@ { "name": "snowplow-tracker", - "version": "2.6.2", + "version": "100.6.3", "devDependencies": { "JSON": "~1.0.0", - "browser-cookie-lite": "~0.3.1", "grunt": "~0.4.2", "grunt-browserify": "~4.0.1", "grunt-contrib-concat": "~0.3.0", @@ -11,14 +10,10 @@ "grunt-aws": "~0.6.1", "grunt-yui-compressor": "git://github.com/snowplow/grunt-yui-compressor.git#0.4.0", "intern": "^3.0.6", - "jstimezonedetect": "1.0.5", "lodash": "^3.1.0", "lodash-cli": "^2.4.2", - "murmurhash": "0.0.2", "semver": "~2.2.1", - "sha1": "git://github.com/pvorb/node-sha1.git#v1.0.0", - "snowplow-tracker-core": "0.3.0", - "uuid": "^2.0.1" + "sha1": "git://github.com/pvorb/node-sha1.git#v1.0.0" }, "contributors": [ "Alex Dean", diff --git a/src/js/forms.js b/src/js/forms.js deleted file mode 100644 index 9053f3e6a..000000000 --- a/src/js/forms.js +++ /dev/null @@ -1,177 +0,0 @@ -/* - * JavaScript tracker for Snowplow: forms.js - * - * Significant portions copyright 2010 Anthon Pang. Remainder copyright - * 2012-2014 Snowplow Analytics Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the - * names of their contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var lodash = require('./lib_managed/lodash'), - helpers = require('./lib/helpers'), - object = typeof exports !== 'undefined' ? exports : this; - -/** - * Object for handling automatic form tracking - * - * @param object core The tracker core - * @param string trackerId Unique identifier for the tracker instance, used to mark tracked elements - * @param function contextAdder Function to add common contexts like PerformanceTiming to all events - * @return object formTrackingManager instance - */ -object.getFormTrackingManager = function (core, trackerId, contextAdder) { - - // Tag names of mutable elements inside a form - var innerElementTags = ['textarea', 'input', 'select']; - - // Used to mark elements with event listeners - var trackingMarker = trackerId + 'form'; - - // Filter to determine which forms should be tracked - var formFilter = function (e) {return true;} - - // Filter to determine which form fields should be tracked - var fieldFilter = function (e) {return true;} - - /* - * Get an identifier for a form, input, textarea, or select element - */ - function getFormElementName(elt) { - return elt[lodash.find(['name', 'id', 'type', 'nodeName'], function (propName) { - - // If elt has a child whose name is "id", that element will be returned - // instead of the actual id of elt unless we ensure that a string is returned - return elt[propName] && typeof elt[propName] === 'string'; - })]; - } - - /* - * Identifies the parent form in which an element is contained - */ - function getParentFormName(elt) { - while (elt && elt.nodeName && elt.nodeName.toUpperCase() !== 'HTML' && elt.nodeName.toUpperCase() !== 'FORM') { - elt = elt.parentNode; - } - if (elt && elt.nodeName && elt.nodeName.toUpperCase() === 'FORM') { - return getFormElementName(elt); - } - } - - /* - * Returns a list of the input, textarea, and select elements inside a form along with their values - */ - function getInnerFormElements(elt) { - var innerElements = []; - lodash.forEach(innerElementTags, function (tagname) { - - var trackedChildren = lodash.filter(elt.getElementsByTagName(tagname), function (child) { - return child.hasOwnProperty(trackingMarker); - }); - - lodash.forEach(trackedChildren, function (child) { - if (child.type === 'submit') { - return; - } - var elementJson = { - name: getFormElementName(child), - value: child.value, - nodeName: child.nodeName - }; - if (child.type && child.nodeName.toUpperCase() === 'INPUT') { - elementJson.type = child.type; - } - - if ((child.type === 'checkbox' || child.type === 'radio') && !child.checked) { - elementJson.value = null; - } - innerElements.push(elementJson); - }); - }); - - return innerElements; - } - - /* - * Return function to handle form field change event - */ - function getFormChangeListener(context) { - return function (e) { - var elt = e.target; - var type = (elt.nodeName && elt.nodeName.toUpperCase() === 'INPUT') ? elt.type : null; - var value = (elt.type === 'checkbox' && !elt.checked) ? null : elt.value; - core.trackFormChange(getParentFormName(elt), getFormElementName(elt), elt.nodeName, type, helpers.getCssClasses(elt), value, contextAdder(context)); - }; - } - - /* - * Return function to handle form submission event - */ - function getFormSubmissionListener(context) { - return function (e) { - var elt = e.target; - var innerElements = getInnerFormElements(elt); - core.trackFormSubmission(getFormElementName(elt), helpers.getCssClasses(elt), innerElements, contextAdder(context)); - }; - } - - return { - - /* - * Configures form tracking: which forms and fields will be tracked, and the context to attach - */ - configureFormTracking: function (config, context) { - if (config) { - formFilter = helpers.getFilter(config.forms, true); - fieldFilter = helpers.getFilter(config.fields, false); - } - }, - - /* - * Add submission event listeners to all form elements - * Add value change event listeners to all mutable inner form elements - */ - addFormListeners: function (context) { - lodash.forEach(document.getElementsByTagName('form'), function (form) { - if (formFilter(form) && !form[trackingMarker]) { - - lodash.forEach(innerElementTags, function (tagname) { - lodash.forEach(form.getElementsByTagName(tagname), function (innerElement) { - if (fieldFilter(innerElement) && !innerElement[trackingMarker]) { - helpers.addEventListener(innerElement, 'change', getFormChangeListener(context), false); - innerElement[trackingMarker] = true; - } - }); - }); - - helpers.addEventListener(form, 'submit', getFormSubmissionListener(context)); - form[trackingMarker] = true; - } - }); - } - }; -}; diff --git a/src/js/in_queue.js b/src/js/in_queue.js index 3fcce6da3..b27f7d1be 100644 --- a/src/js/in_queue.js +++ b/src/js/in_queue.js @@ -36,7 +36,6 @@ var lodash = require('./lib_managed/lodash'), - helpers = require('./lib/helpers'), object = typeof exports !== 'undefined' ? exports : this; // For eventual node.js environment support @@ -46,7 +45,7 @@ * after the Tracker has been initialized and loaded ************************************************************/ - object.InQueueManager = function(TrackerConstructor, version, pageViewId, mutSnowplowState, asyncQueue, functionName) { + object.InQueueManager = function(TrackerConstructor, version, mutSnowplowState, asyncQueue, functionName) { // Page view ID should be shared between all tracker instances var trackerDictionary = {}; @@ -66,41 +65,17 @@ if (trackerDictionary.hasOwnProperty(names[i])) { namedTrackers.push(trackerDictionary[names[i]]); } else { - helpers.warn('Warning: Tracker namespace "' + names[i] + '" not configured'); } } } if (namedTrackers.length === 0) { - helpers.warn('Warning: No tracker configured'); } return namedTrackers; } - /** - * Legacy support for input of the form _snaq.push(['setCollectorCf', 'd34uzc5hjrimh8']) - * - * @param string f Either 'setCollectorCf' or 'setCollectorUrl' - * @param string endpoint - * @param string namespace Optional tracker name - * - * TODO: remove this in 2.1.0 - */ - function legacyCreateNewNamespace(f, endpoint, namespace) { - helpers.warn(f + ' is deprecated. Set the collector when a new tracker instance using newTracker.'); - var name; - - if (lodash.isUndefined(namespace)) { - name = 'sp'; - } else { - name = namespace; - } - - createNewNamespace(name); - trackerDictionary[name][f](endpoint); - } /** * Initiate a new tracker namespace @@ -112,10 +87,9 @@ argmap = argmap || {}; if (!trackerDictionary.hasOwnProperty(namespace)) { - trackerDictionary[namespace] = new TrackerConstructor(functionName, namespace, version, pageViewId, mutSnowplowState, argmap); + trackerDictionary[namespace] = new TrackerConstructor(functionName, namespace, version, mutSnowplowState, argmap); trackerDictionary[namespace].setCollectorUrl(endpoint); } else { - helpers.warn('Tracker namespace ' + namespace + ' already exists.'); } } diff --git a/src/js/lib/detectors.js b/src/js/lib/detectors.js index 4e357da61..37f1062bb 100644 --- a/src/js/lib/detectors.js +++ b/src/js/lib/detectors.js @@ -35,10 +35,6 @@ ;(function() { var - lodash = require('../lib_managed/lodash'), - murmurhash3_32_gc = require('murmurhash').v3, - tz = require('jstimezonedetect').jstz.determine(), - cookie = require('browser-cookie-lite'), object = typeof exports !== 'undefined' ? exports : this, // For eventual node.js environment support @@ -92,162 +88,6 @@ } }; - /* - * Does browser have cookies enabled (for this site)? - */ - object.hasCookies = function(testCookieName) { - var cookieName = testCookieName || 'testcookie'; - - if (lodash.isUndefined(navigatorAlias.cookieEnabled)) { - cookie.cookie(cookieName, '1'); - return cookie.cookie(cookieName) === '1' ? '1' : '0'; - } - - return navigatorAlias.cookieEnabled ? '1' : '0'; - }; - - /** - * JS Implementation for browser fingerprint. - * Does not require any external resources. - * Based on https://github.com/carlo/jquery-browser-fingerprint - * @return {number} 32-bit positive integer hash - */ - object.detectSignature = function(hashSeed) { - - var fingerprint = [ - navigatorAlias.userAgent, - [ screenAlias.height, screenAlias.width, screenAlias.colorDepth ].join("x"), - ( new Date() ).getTimezoneOffset(), - object.hasSessionStorage(), - object.hasLocalStorage() - ]; - - var plugins = []; - if (navigatorAlias.plugins) - { - for(var i = 0; i < navigatorAlias.plugins.length; i++) - { - if (navigatorAlias.plugins[i]) { - var mt = []; - for(var j = 0; j < navigatorAlias.plugins[i].length; j++) { - mt.push([navigatorAlias.plugins[i][j].type, navigatorAlias.plugins[i][j].suffixes]); - } - plugins.push([navigatorAlias.plugins[i].name + "::" + navigatorAlias.plugins[i].description, mt.join("~")]); - } - } - } - return murmurhash3_32_gc(fingerprint.join("###") + "###" + plugins.sort().join(";"), hashSeed); - }; - - /* - * Returns visitor timezone - */ - object.detectTimezone = function() { - return (typeof (tz) === 'undefined') ? '' : tz.name(); - }; - /** - * Gets the current viewport. - * - * Code based on: - * - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/ - * - http://responsejs.com/labs/dimensions/ - */ - object.detectViewport = function() { - var e = windowAlias, a = 'inner'; - if (!('innerWidth' in windowAlias)) { - a = 'client'; - e = documentAlias.documentElement || documentAlias.body; - } - var width = e[a+'Width']; - var height = e[a+'Height']; - if (width >= 0 && height >= 0) { - return width + 'x' + height; - } else { - return null; - } - }; - - /** - * Gets the dimensions of the current - * document. - * - * Code based on: - * - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/ - */ - object.detectDocumentSize = function() { - var de = documentAlias.documentElement, // Alias - be = documentAlias.body, - - // document.body may not have rendered, so check whether be.offsetHeight is null - bodyHeight = be ? Math.max(be.offsetHeight, be.scrollHeight) : 0; - var w = Math.max(de.clientWidth, de.offsetWidth, de.scrollWidth); - var h = Math.max(de.clientHeight, de.offsetHeight, de.scrollHeight, bodyHeight); - return isNaN(w) || isNaN(h) ? '' : w + 'x' + h; - }; - - /** - * Returns browser features (plugins, resolution, cookies) - * - * @param boolean useCookies Whether to test for cookies - * @param string testCookieName Name to use for the test cookie - * @return Object containing browser features - */ - object.detectBrowserFeatures = function(useCookies, testCookieName) { - var i, - mimeType, - pluginMap = { - // document types - pdf: 'application/pdf', - - // media players - qt: 'video/quicktime', - realp: 'audio/x-pn-realaudio-plugin', - wma: 'application/x-mplayer2', - - // interactive multimedia - dir: 'application/x-director', - fla: 'application/x-shockwave-flash', - - // RIA - java: 'application/x-java-vm', - gears: 'application/x-googlegears', - ag: 'application/x-silverlight' - }, - features = {}; - - // General plugin detection - if (navigatorAlias.mimeTypes && navigatorAlias.mimeTypes.length) { - for (i in pluginMap) { - if (Object.prototype.hasOwnProperty.call(pluginMap, i)) { - mimeType = navigatorAlias.mimeTypes[pluginMap[i]]; - features[i] = (mimeType && mimeType.enabledPlugin) ? '1' : '0'; - } - } - } - - // Safari and Opera - // IE6/IE7 navigator.javaEnabled can't be aliased, so test directly - if (navigatorAlias.constructor === window.Navigator && - typeof navigatorAlias.javaEnabled !== 'unknown' && - !lodash.isUndefined(navigatorAlias.javaEnabled) && - navigatorAlias.javaEnabled()) { - features.java = '1'; - } - - // Firefox - if (lodash.isFunction(windowAlias.GearsFactory)) { - features.gears = '1'; - } - - // Other browser features - features.res = screenAlias.width + 'x' + screenAlias.height; - features.cd = screenAlias.colorDepth; - if (useCookies) { - features.cookie = object.hasCookies(testCookieName); - } - - return features; - }; }()); diff --git a/src/js/lib/helpers.js b/src/js/lib/helpers.js index 518c9d3a5..0dfd5602b 100644 --- a/src/js/lib/helpers.js +++ b/src/js/lib/helpers.js @@ -35,7 +35,6 @@ var lodash = require('../lib_managed/lodash'), - cookie = require('browser-cookie-lite'), object = typeof exports !== 'undefined' ? exports : this; // For eventual node.js environment support @@ -82,48 +81,7 @@ return domain; }; - /** - * Get page referrer. In the case of a single-page app, - * if the URL changes without the page reloading, pass - * in the old URL. It will be returned unless overriden - * by a "refer(r)er" parameter in the querystring. - * - * @param string oldLocation Optional. - * @return string The referrer - */ - object.getReferrer = function (oldLocation) { - - var referrer = ''; - - var fromQs = object.fromQuerystring('referrer', window.location.href) || - object.fromQuerystring('referer', window.location.href); - - // Short-circuit - if (fromQs) { - return fromQs; - } - - // In the case of a single-page app, return the old URL - if (oldLocation) { - return oldLocation; - } - - try { - referrer = window.top.document.referrer; - } catch (e) { - if (window.parent) { - try { - referrer = window.parent.document.referrer; - } catch (e2) { - referrer = ''; - } - } - } - if (referrer === '') { - referrer = document.referrer; - } - return referrer; - }; + /* * Cross-browser helper function to add event handler @@ -155,7 +113,7 @@ */ object.warn = function(message) { if (typeof console !== 'undefined') { - console.warn('Snowplow: ' + message); + //console.warn('Snowplow: ' + message); } }; diff --git a/src/js/links.js b/src/js/links.js deleted file mode 100644 index de2b5591d..000000000 --- a/src/js/links.js +++ /dev/null @@ -1,199 +0,0 @@ -/* - * JavaScript tracker for Snowplow: links.js - * - * Significant portions copyright 2010 Anthon Pang. Remainder copyright - * 2012-2014 Snowplow Analytics Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of Anthon Pang nor Snowplow Analytics Ltd nor the - * names of their contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var lodash = require('./lib_managed/lodash'), - helpers = require('./lib/helpers'), - object = typeof exports !== 'undefined' ? exports : this; - -/** - * Object for handling automatic link tracking - * - * @param object core The tracker core - * @param string trackerId Unique identifier for the tracker instance, used to mark tracked links - * @param function contextAdder Function to add common contexts like PerformanceTiming to all events - * @return object linkTrackingManager instance - */ -object.getLinkTrackingManager = function (core, trackerId, contextAdder) { - - // Filter function used to determine whether clicks on a link should be tracked - var linkTrackingFilter, - - // Whether pseudo clicks are tracked - linkTrackingPseudoClicks, - - // Whether to track the innerHTML of clicked links - linkTrackingContent, - - // The context attached to link click events - linkTrackingContext, - - // Internal state of the pseudo click handler - lastButton, - lastTarget; - - /* - * Process clicks - */ - function processClick(sourceElement, context) { - - var parentElement, - tag, - elementId, - elementClasses, - elementTarget, - elementContent; - - while ((parentElement = sourceElement.parentNode) !== null && - !lodash.isUndefined(parentElement) && // buggy IE5.5 - ((tag = sourceElement.tagName.toUpperCase()) !== 'A' && tag !== 'AREA')) { - sourceElement = parentElement; - } - - if (!lodash.isUndefined(sourceElement.href)) { - // browsers, such as Safari, don't downcase hostname and href - var originalSourceHostName = sourceElement.hostname || helpers.getHostName(sourceElement.href), - sourceHostName = originalSourceHostName.toLowerCase(), - sourceHref = sourceElement.href.replace(originalSourceHostName, sourceHostName), - scriptProtocol = new RegExp('^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):', 'i'); - - // Ignore script pseudo-protocol links - if (!scriptProtocol.test(sourceHref)) { - - elementId = sourceElement.id; - elementClasses = helpers.getCssClasses(sourceElement); - elementTarget = sourceElement.target; - elementContent = linkTrackingContent ? sourceElement.innerHTML : null; - - // decodeUrl %xx - sourceHref = unescape(sourceHref); - core.trackLinkClick(sourceHref, elementId, elementClasses, elementTarget, elementContent, contextAdder(context)); - } - } - } - - /* - * Return function to handle click event - */ - function getClickHandler(context) { - return function (evt) { - var button, - target; - - evt = evt || window.event; - button = evt.which || evt.button; - target = evt.target || evt.srcElement; - - // Using evt.type (added in IE4), we avoid defining separate handlers for mouseup and mousedown. - if (evt.type === 'click') { - if (target) { - processClick(target, context); - } - } else if (evt.type === 'mousedown') { - if ((button === 1 || button === 2) && target) { - lastButton = button; - lastTarget = target; - } else { - lastButton = lastTarget = null; - } - } else if (evt.type === 'mouseup') { - if (button === lastButton && target === lastTarget) { - processClick(target, context); - } - lastButton = lastTarget = null; - } - }; - } - - /* - * Add click listener to a DOM element - */ - function addClickListener(element) { - if (linkTrackingPseudoClicks) { - // for simplicity and performance, we ignore drag events - helpers.addEventListener(element, 'mouseup', getClickHandler(linkTrackingContext), false); - helpers.addEventListener(element, 'mousedown', getClickHandler(linkTrackingContext), false); - } else { - helpers.addEventListener(element, 'click', getClickHandler(linkTrackingContext), false); - } - } - - - - /* - * Check whether a set of classes contains any of the classes of a link element - * Used to determine whether clicks on that link should be tracked - */ - function checkLink(linkElement, specifiedClasses) { - var linkClasses = helpers.getCssClasses(linkElement), - i; - - for (i = 0; i < linkClasses.length; i++) { - if (specifiedClasses[linkClasses[i]]) { - return true; - } - } - return false; - } - - return { - - /* - * Configures link click tracking: how to filter which links will be tracked, - * whether to use pseudo click tracking, and what context to attach to link_click events - */ - configureLinkClickTracking: function (criterion, pseudoClicks, trackContent, context) { - linkTrackingContent = trackContent; - linkTrackingContext = context; - linkTrackingPseudoClicks = pseudoClicks; - linkTrackingFilter = helpers.getFilter(criterion, true); - }, - - /* - * Add click handlers to anchor and AREA elements, except those to be ignored - */ - addClickListeners: function () { - - var linkElements = document.links, - i; - - for (i = 0; i < linkElements.length; i++) { - // Add a listener to link elements which pass the filter and aren't already tracked - if (linkTrackingFilter(linkElements[i]) && !linkElements[i][trackerId]) { - addClickListener(linkElements[i]); - linkElements[i][trackerId] = true; - } - } - } - }; -}; diff --git a/src/js/out_queue.js b/src/js/out_queue.js index f57a17aeb..7fb1d7758 100644 --- a/src/js/out_queue.js +++ b/src/js/out_queue.js @@ -50,27 +50,25 @@ * @param object mutSnowplowState Gives the pageUnloadGuard a reference to the outbound queue * so it can unload the page when all queues are empty * @param boolean useLocalStorage Whether to use localStorage at all - * @param boolean usePost Whether to send events by POST or GET * @param int bufferSize How many events to batch in localStorage before sending them all. * Only applies when sending POST requests and when localStorage is available. * @param int maxPostBytes Maximum combined size in bytes of the event JSONs in a POST request * @return object OutQueueManager instance */ - object.OutQueueManager = function (functionName, namespace, mutSnowplowState, useLocalStorage, usePost, bufferSize, maxPostBytes) { + object.OutQueueManager = function (functionName, namespace, mutSnowplowState, useLocalStorage, bufferSize, maxPostBytes,configUseSecureCredentials,configCollectorToken) { + + var usePost=true; + var queueName, executingQueue = false, configCollectorUrl, outQueue; - // Fall back to GET for browsers which don't support CORS XMLHttpRequests (e.g. IE <= 9) - usePost = usePost && window.XMLHttpRequest && ('withCredentials' in new XMLHttpRequest()); + var path = '/com.snowplowanalytics.snowplow/tp2'; - var path = usePost ? '/com.snowplowanalytics.snowplow/tp2' : '/i'; + bufferSize = (localStorageAccessible() && useLocalStorage && bufferSize) || 1; - bufferSize = (localStorageAccessible() && useLocalStorage && usePost && bufferSize) || 1; - - // Different queue names for GET and POST since they are stored differently - queueName = ['snowplowOutQueue', functionName, namespace, usePost ? 'post2' : 'get'].join('_'); + queueName = ['snowplowOutQueue', functionName, namespace, 'post2'].join('_'); if (useLocalStorage) { // Catch any JSON parse errors or localStorage that might be thrown @@ -89,55 +87,15 @@ // Used by pageUnloadGuard mutSnowplowState.outQueues.push(outQueue); - if (usePost && bufferSize > 1) { + if (bufferSize > 1) { mutSnowplowState.bufferFlushers.push(function () { if (!executingQueue) { - executeQueue(); + executeQueue(configUseSecureCredentials,configCollectorToken); } }); } - /* - * Convert a dictionary to a querystring - * The context field is the last in the querystring - */ - function getQuerystring(request) { - var querystring = '?', - lowPriorityKeys = {'co': true, 'cx': true}, - firstPair = true; - - for (var key in request) { - if (request.hasOwnProperty(key) && !(lowPriorityKeys.hasOwnProperty(key))) { - if (!firstPair) { - querystring += '&'; - } else { - firstPair = false; - } - querystring += encodeURIComponent(key) + '=' + encodeURIComponent(request[key]); - } - } - - for (var contextKey in lowPriorityKeys) { - if (request.hasOwnProperty(contextKey) && lowPriorityKeys.hasOwnProperty(contextKey)) { - querystring += '&' + contextKey + '=' + encodeURIComponent(request[contextKey]); - } - } - return querystring; - } - - /* - * Convert numeric fields to strings to match payload_data schema - */ - function getBody(request) { - var cleanedRequest = lodash.mapValues(request, function (v) { - return v.toString(); - }); - return { - evt: cleanedRequest, - bytes: getUTF8Length(json2.stringify(cleanedRequest)) - }; - } /** * Count the number of bytes a string will occupy when UTF-8 encoded @@ -171,29 +129,37 @@ * Queue an image beacon for submission to the collector. * If we're not processing the queue, we'll start. */ - function enqueueRequest (request, url) { + function enqueueRequest (request, url,configUseSecureCredentials,configCollectorToken) { configCollectorUrl = url + path; - if (usePost) { - var body = getBody(request); - if (body.bytes >= maxPostBytes) { - helpers.warn("Event of size " + body.bytes + " is too long - the maximum size is " + maxPostBytes); - var xhr = initializeXMLHttpRequest(configCollectorUrl); - xhr.send(encloseInPayloadDataEnvelope(attachStmToEvent([body.evt]))); - return; - } else { - outQueue.push(body); + var event=request; + var body = { + evt: event, + bytes: getUTF8Length(json2.stringify(event)) + }; + // not working for browsers which don't support CORS XMLHttpRequests (e.g. IE <= 9) + hasPost = window.XMLHttpRequest && ('withCredentials' in new XMLHttpRequest()); + + if (body.bytes >= maxPostBytes) { + helpers.warn("Event of size " + body.bytes + " is too long - the maximum size is " + maxPostBytes); + if (hasPost){ + var xhr = initializeXMLHttpRequest(configCollectorUrl,configUseSecureCredentials,configCollectorToken); + xhr.send(json2.stringify([body.evt])); + }else{ + helpers.warn("Browser doesn't support secure credentials"); } + return; } else { - outQueue.push(getQuerystring(request)); + outQueue.push(body); } + var savedToLocalStorage = false; if (useLocalStorage) { savedToLocalStorage = helpers.attemptWriteLocalStorage(queueName, json2.stringify(outQueue)); } if (!executingQueue && (!savedToLocalStorage || outQueue.length >= bufferSize)) { - executeQueue(); + executeQueue(configUseSecureCredentials,configCollectorToken); } } @@ -201,7 +167,7 @@ * Run through the queue of image beacons, sending them one at a time. * Stops processing when we run out of queued requests, or we get an error. */ - function executeQueue () { + function executeQueue (configUseSecureCredentials,configCollectorToken) { // Failsafe in case there is some way for a bad value like "null" to end up in the outQueue while (outQueue.length && typeof outQueue[0] !== 'string' && typeof outQueue[0] !== 'object') { @@ -222,75 +188,58 @@ var nextRequest = outQueue[0]; - if (usePost) { - - var xhr = initializeXMLHttpRequest(configCollectorUrl); + - // Time out POST requests after 5 seconds - var xhrTimeout = setTimeout(function () { - xhr.abort(); - executingQueue = false; - }, 5000); - - function chooseHowManyToExecute(q) { - var numberToSend = 0; - var byteCount = 0; - while (numberToSend < q.length) { - byteCount += q[numberToSend].bytes; - if (byteCount >= maxPostBytes) { - break; - } else { - numberToSend += 1; - } - } - return numberToSend; - } + var xhr = initializeXMLHttpRequest(configCollectorUrl,configUseSecureCredentials,configCollectorToken); - // Keep track of number of events to delete from queue - var numberToSend = chooseHowManyToExecute(outQueue); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 400) { - for (var deleteCount = 0; deleteCount < numberToSend; deleteCount++) { - outQueue.shift(); - } - if (useLocalStorage) { - helpers.attemptWriteLocalStorage(queueName, json2.stringify(outQueue)); - } - clearTimeout(xhrTimeout); - executeQueue(); - } else if (xhr.readyState === 4 && xhr.status >= 400) { - clearTimeout(xhrTimeout); - executingQueue = false; + // Time out POST requests after Q seconds + var xhrTimeout = setTimeout(function () { + xhr.abort(); + executingQueue = false; + }, 1000); + + function chooseHowManyToExecute(q) { + var numberToSend = 0; + var byteCount = 0; + while (numberToSend < q.length) { + byteCount += q[numberToSend].bytes; + if (byteCount >= maxPostBytes) { + break; + } else { + numberToSend += 1; } - }; - - var batch = lodash.map(outQueue.slice(0, numberToSend), function (x) { - return x.evt; - }); - - if (batch.length > 0) { - xhr.send(encloseInPayloadDataEnvelope(attachStmToEvent(batch))); } + return numberToSend; + } - } else { - - var image = new Image(1, 1); + // Keep track of number of events to delete from queue + var numberToSend = chooseHowManyToExecute(outQueue); - image.onload = function () { - outQueue.shift(); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 400) { + for (var deleteCount = 0; deleteCount < numberToSend; deleteCount++) { + outQueue.shift(); + } if (useLocalStorage) { helpers.attemptWriteLocalStorage(queueName, json2.stringify(outQueue)); } - executeQueue(); - }; - - image.onerror = function () { + clearTimeout(xhrTimeout); + executeQueue(configUseSecureCredentials,configCollectorToken); + } else if (xhr.readyState === 4 && xhr.status >= 400) { + clearTimeout(xhrTimeout); executingQueue = false; - }; + } + }; + + var batch = lodash.map(outQueue.slice(0, numberToSend), function (x) { + return x.evt; + }); - image.src = configCollectorUrl + nextRequest.replace('?', '?stm=' + new Date().getTime() + '&'); + if (batch.length > 0) { + xhr.send(json2.stringify(batch)); } + + } /** @@ -299,39 +248,17 @@ * @param string url The destination URL * @return object The XMLHttpRequest */ - function initializeXMLHttpRequest(url) { + function initializeXMLHttpRequest(url,configUseSecureCredentials,configCollectorToken) { var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); - xhr.withCredentials = true; + xhr.withCredentials = configUseSecureCredentials; xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); + xhr.setRequestHeader("x-api-key",configCollectorToken) return xhr; } - /** - * Enclose an array of events in a self-describing payload_data JSON string - * - * @param array events Batch of events - * @return string payload_data self-describing JSON - */ - function encloseInPayloadDataEnvelope(events) { - return json2.stringify({ - schema: 'iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-3', - data: events - }); - } - /** - * Attaches the STM field to outbound POST events. - * - * @param events the events to attach the STM to - */ - function attachStmToEvent(events) { - var stm = new Date().getTime().toString(); - for (var i = 0; i < events.length; i++) { - events[i]['stm'] = stm; - } - return events - } + return { enqueueRequest: enqueueRequest, diff --git a/src/js/snowplow.js b/src/js/snowplow.js index b8c57d24d..7c90f72ab 100644 --- a/src/js/snowplow.js +++ b/src/js/snowplow.js @@ -75,7 +75,6 @@ // Load all our modules (at least until we fully modularize & remove grunt-concat) var - uuid = require('uuid'), lodash = require('./lib_managed/lodash'), helpers = require('./lib/helpers'), queue = require('./in_queue'), @@ -92,7 +91,6 @@ /* Tracker identifier with version */ version = 'js-' + '<%= pkg.version %>', // Update banner.js too - pageViewId = uuid.v4(), /* Contains four variables that are shared with tracker.js and must be passed by reference */ mutSnowplowState = { @@ -223,7 +221,7 @@ * @param string distSubdomain The subdomain on your CloudFront collector's distribution */ getTrackerCf: function (distSubdomain) { - var t = new tracker.Tracker(functionName, '', version, pageViewId, mutSnowplowState, {}); + var t = new tracker.Tracker(functionName, '', version, mutSnowplowState, {}); t.setCollectorCf(distSubdomain); return t; }, @@ -235,7 +233,7 @@ * @param string rawUrl The collector URL minus protocol and /i */ getTrackerUrl: function (rawUrl) { - var t = new tracker.Tracker(functionName, '', version, pageViewId, mutSnowplowState, {}); + var t = new tracker.Tracker(functionName, '', version, mutSnowplowState, {}); t.setCollectorUrl(rawUrl); return t; }, @@ -246,7 +244,7 @@ * @return Tracker */ getAsyncTracker: function () { - return new tracker.Tracker(functionName, '', version, pageViewId, mutSnowplowState, {}); + return new tracker.Tracker(functionName, '', version, mutSnowplowState, {}); } }; @@ -259,7 +257,7 @@ addReadyListener(); // Now replace initialization array with queue manager object - return new queue.InQueueManager(tracker.Tracker, version, pageViewId, mutSnowplowState, asynchronousQueue, functionName); + return new queue.InQueueManager(tracker.Tracker, version, mutSnowplowState, asynchronousQueue, functionName); }; }()); diff --git a/src/js/tracker.js b/src/js/tracker.js index b46e02142..b77fdb65b 100644 --- a/src/js/tracker.js +++ b/src/js/tracker.js @@ -35,148 +35,49 @@ ;(function() { var - lodash = require('./lib_managed/lodash'), - helpers = require('./lib/helpers'), - proxies = require('./lib/proxies'), - cookie = require('browser-cookie-lite'), - detectors = require('./lib/detectors'), json2 = require('JSON'), sha1 = require('sha1'), - links = require('./links'), - forms = require('./forms'), requestQueue = require('./out_queue'), - coreConstructor = require('snowplow-tracker-core'), - uuid = require('uuid'), object = typeof exports !== 'undefined' ? exports : this; // For eventual node.js environment support - /** - * Snowplow Tracker class - * - * @param namespace The namespace of the tracker object - * @param version The current version of the JavaScript Tracker - * - * @param pageViewId ID for the current page view, to be attached to all events in the web_page context - * - * @param mutSnowplowState An object containing hasLoaded, registeredOnLoadHandlers, and expireDateTime - * Passed in by reference in case they are altered by snowplow.js - * - * @param argmap Optional dictionary of configuration options. Supported fields and their default values: - * - * 1. encodeBase64, true - * 2. cookieDomain, null - * 3. cookieName, '_sp_' - * 4. appId, '' - * 5. platform, 'web' - * 6. respectDoNotTrack, false - * 7. userFingerprint, true - * 8. userFingerprintSeed, 123412414 - * 9. pageUnloadTimer, 500 - * 10. forceSecureTracker, false - * 11. forceUnsecureTracker, false - * 12. useLocalStorage, true - * 13. useCookies, true - * 14. sessionCookieTimeout, 1800 - * 15. contexts, {} - * 16. post, false - * 17. bufferSize, 1 - * 18. crossDomainLinker, false - * 19. maxPostBytes, 40000 - * 20. discoverRootDomain, false - */ - object.Tracker = function Tracker(functionName, namespace, version, pageViewId, mutSnowplowState, argmap) { + object.Tracker = function Tracker(functionName, namespace, version, mutSnowplowState, argmap) { /************************************************************ * Private members ************************************************************/ var - // Tracker core - core = coreConstructor(true, function(payload) { - addBrowserData(payload); - sendRequest(payload, configTrackerPause); - }), // Aliases documentAlias = document, windowAlias = window, navigatorAlias = navigator, - // Current URL and Referrer URL - locationArray = proxies.fixupUrl(documentAlias.domain, windowAlias.location.href, helpers.getReferrer()), - domainAlias = helpers.fixupDomain(locationArray[0]), - locationHrefAlias = locationArray[1], - configReferrerUrl = locationArray[2], - customReferrer, argmap = argmap || {}, - // Request method is always GET for Snowplow - configRequestMethod = 'GET', - - // Platform defaults to web for this tracker - configPlatform = argmap.hasOwnProperty('platform') ? argmap.platform : 'web', + // token if needed for post + configCollectorToken = argmap.hasOwnProperty('token') ? argmap.token: '', + // use secure credenmtials + configUseSecureCredentials = argmap.hasOwnProperty('useSecureCredentials') ? argmap.secureCredentials: false, + // Snowplow collector URL configCollectorUrl, - // Site ID - configTrackerSiteId = argmap.hasOwnProperty('appId') ? argmap.appId : '', // Updated for Snowplow - - // Document URL - configCustomUrl, - - // Document title - lastDocumentTitle = documentAlias.title, - - // Custom title - lastConfigTitle, - + // Maximum delay to wait for web bug image to be fetched (in milliseconds) configTrackerPause = argmap.hasOwnProperty('pageUnloadTimer') ? argmap.pageUnloadTimer : 500, - // Minimum visit time after initial page view (in milliseconds) - configMinimumVisitTime, - - // Recurring heart beat after initial ping (in milliseconds) - configHeartBeatTimer, - - // Disallow hash tags in URL. TODO: Should this be set to true by default? - configDiscardHashTag, - - // First-party cookie name prefix - configCookieNamePrefix = argmap.hasOwnProperty('cookieName') ? argmap.cookieName : '_sp_', - - // First-party cookie domain - // User agent defaults to origin hostname - configCookieDomain = argmap.hasOwnProperty('cookieDomain') ? argmap.cookieDomain : null, - - // First-party cookie path - // Default is user agent defined. - configCookiePath = '/', - // Do Not Track browser feature dnt = navigatorAlias.doNotTrack || navigatorAlias.msDoNotTrack || windowAlias.doNotTrack, // Do Not Track configDoNotTrack = argmap.hasOwnProperty('respectDoNotTrack') ? argmap.respectDoNotTrack && (dnt === 'yes' || dnt === '1') : false, - // Count sites which are pre-rendered - configCountPreRendered, - - // Life of the visitor cookie (in seconds) - configVisitorCookieTimeout = 63072000, // 2 years - - // Life of the session cookie (in seconds) - configSessionCookieTimeout = argmap.hasOwnProperty('sessionCookieTimeout') ? argmap.sessionCookieTimeout : 1800, // 30 minutes - - // Default hash seed for MurmurHash3 in detectors.detectSignature - configUserFingerprintHashSeed = argmap.hasOwnProperty('userFingerprintSeed') ? argmap.userFingerprintSeed : 123412414, - - // Document character set - documentCharset = documentAlias.characterSet || documentAlias.charset, - + // This forces the tracker to be HTTPS even if the page is not secure forceSecureTracker = argmap.hasOwnProperty('forceSecureTracker') ? (argmap.forceSecureTracker === true) : false, @@ -186,239 +87,33 @@ // Whether to use localStorage to store events between sessions while offline useLocalStorage = argmap.hasOwnProperty('useLocalStorage') ? argmap.useLocalStorage : true, - // Whether to use cookies - configUseCookies = argmap.hasOwnProperty('useCookies') ? argmap.useCookies : true, - - // Browser language (or Windows language for IE). Imperfect but CloudFront doesn't log the Accept-Language header - browserLanguage = navigatorAlias.userLanguage || navigatorAlias.language, - - // Browser features via client-side data collection - browserFeatures = detectors.detectBrowserFeatures(configUseCookies, getSnowplowCookieName('testcookie')), - - // Visitor fingerprint - userFingerprint = (argmap.userFingerprint === false) ? '' : detectors.detectSignature(configUserFingerprintHashSeed), - - // Unique ID for the tracker instance used to mark links which are being tracked - trackerId = functionName + '_' + namespace, - - // Guard against installing the activity tracker more than once per Tracker instance - activityTrackingInstalled = false, - + // Last activity timestamp lastActivityTime, // The last time an event was fired on the page - used to invalidate session if cookies are disabled lastEventTime = new Date().getTime(), - // How are we scrolling? - minXOffset, - maxXOffset, - minYOffset, - maxYOffset, + // Hash function hash = sha1, - // Domain hash value - domainHash, - - // Domain unique user ID - domainUserId, - - // ID for the current session - memorizedSessionId, - - // Index for the current session - kept in memory in case cookies are disabled - memorizedVisitCount = 1, - - // Business-defined unique user ID - businessUserId, - - // Ecommerce transaction data - // Will be committed, sent and emptied by a call to trackTrans. - ecommerceTransaction = ecommerceTransactionTemplate(), - - // Manager for automatic link click tracking - linkTrackingManager = links.getLinkTrackingManager(core, trackerId, addCommonContexts), - - // Manager for automatic form tracking - formTrackingManager = forms.getFormTrackingManager(core, trackerId, addCommonContexts), - + // Manager for local storage queue outQueueManager = new requestQueue.OutQueueManager( functionName, namespace, mutSnowplowState, useLocalStorage, - argmap.post, argmap.bufferSize, - argmap.maxPostBytes || 40000), - - // Flag to prevent the geolocation context being added multiple times - geolocationContextAdded = false, - - // Set of contexts to be added to every event - autoContexts = argmap.contexts || {}, - - // Context to be added to every event - commonContexts = [], - - // Enhanced Ecommerce Contexts to be added on every `trackEnhancedEcommerceAction` call - enhancedEcommerceContexts = []; - - if (argmap.hasOwnProperty('discoverRootDomain') && argmap.discoverRootDomain) { - configCookieDomain = helpers.findRootDomain(); - } - - if (autoContexts.webPage) { - commonContexts.push(getWebPageContext()); - } - - if (autoContexts.gaCookies) { - commonContexts.push(getGaCookiesContext()); - } - - if (autoContexts.geolocation) { - enableGeolocationContext(); - } - - // Enable base 64 encoding for unstructured events and custom contexts - core.setBase64Encoding(argmap.hasOwnProperty('encodeBase64') ? argmap.encodeBase64 : true); - - // Set up unchanging name-value pairs - core.setTrackerVersion(version); - core.setTrackerNamespace(namespace); - core.setAppId(configTrackerSiteId); - core.setPlatform(configPlatform); - core.setTimezone(detectors.detectTimezone()); - core.addPayloadPair('lang', browserLanguage); - core.addPayloadPair('cs', documentCharset); - - // Browser features. Cookies, color depth and resolution don't get prepended with f_ (because they're not optional features) - for (var i in browserFeatures) { - if (Object.prototype.hasOwnProperty.call(browserFeatures, i)) { - if (i === 'res' || i === 'cd' || i === 'cookie') { - core.addPayloadPair(i, browserFeatures[i]); - } else { - core.addPayloadPair('f_' + i, browserFeatures[i]); - } - } - } - - /** - * Recalculate the domain, URL, and referrer - */ - function refreshUrl() { - locationArray = proxies.fixupUrl(documentAlias.domain, windowAlias.location.href, helpers.getReferrer()); - - // If this is a single-page app and the page URL has changed, then: - // - if the new URL's querystring contains a "refer(r)er" parameter, use it as the referrer - // - otherwise use the old URL as the referer - if (locationArray[1] !== locationHrefAlias) { - configReferrerUrl = helpers.getReferrer(locationHrefAlias); - } - - domainAlias = helpers.fixupDomain(locationArray[0]); - locationHrefAlias = locationArray[1]; - } - - /** - * Decorate the querystring of a single link - * - * @param event e The event targeting the link - */ - function linkDecorationHandler(e) { - var tstamp = new Date().getTime(); - var initialQsParams = '_sp=' + domainUserId + '.' + tstamp; - if (this.href) { - this.href = helpers.decorateQuerystring(this.href, '_sp', domainUserId + '.' + tstamp); - } - } - - /** - * Enable querystring decoration for links pasing a filter - * Whenever such a link is clicked on or navigated to via the keyboard, - * add "_sp={{duid}}.{{timestamp}}" to its querystring - * - * @param function crossDomainLinker Function used to determine which links to decorate - */ - function decorateLinks(crossDomainLinker) { - for (var i=0; i= 0) { - baseUrl = baseUrl.slice(0, i); - } - if ((i = baseUrl.lastIndexOf('/')) !== baseUrl.length - 1) { - baseUrl = baseUrl.slice(0, i + 1); - } + - return baseUrl + url; - } + /* * Send request @@ -427,301 +122,11 @@ var now = new Date(); if (!configDoNotTrack) { - outQueueManager.enqueueRequest(request.build(), configCollectorUrl); + outQueueManager.enqueueRequest(request, configCollectorUrl,configUseSecureCredentials,configCollectorToken); mutSnowplowState.expireDateTime = now.getTime() + delay; } } - /* - * Get cookie name with prefix and domain hash - */ - function getSnowplowCookieName(baseName) { - return configCookieNamePrefix + baseName + '.' + domainHash; - } - - /* - * Cookie getter. - */ - function getSnowplowCookieValue(cookieName) { - return cookie.cookie(getSnowplowCookieName(cookieName)); - } - - /* - * Update domain hash - */ - function updateDomainHash() { - refreshUrl(); - domainHash = hash((configCookieDomain || domainAlias) + (configCookiePath || '/')).slice(0, 4); // 4 hexits = 16 bits - } - - /* - * Process all "activity" events. - * For performance, this function must have low overhead. - */ - function activityHandler() { - var now = new Date(); - lastActivityTime = now.getTime(); - } - - /* - * Process all "scroll" events. - */ - function scrollHandler() { - updateMaxScrolls(); - activityHandler(); - } - - /* - * Returns [pageXOffset, pageYOffset]. - * Adapts code taken from: http://www.javascriptkit.com/javatutors/static2.shtml - */ - function getPageOffsets() { - var iebody = (documentAlias.compatMode && documentAlias.compatMode != "BackCompat") ? - documentAlias.documentElement : - documentAlias.body; - return [iebody.scrollLeft || windowAlias.pageXOffset, iebody.scrollTop || windowAlias.pageYOffset]; - } - - /* - * Quick initialization/reset of max scroll levels - */ - function resetMaxScrolls() { - var offsets = getPageOffsets(); - - var x = offsets[0]; - minXOffset = x; - maxXOffset = x; - - var y = offsets[1]; - minYOffset = y; - maxYOffset = y; - } - - /* - * Check the max scroll levels, updating as necessary - */ - function updateMaxScrolls() { - var offsets = getPageOffsets(); - - var x = offsets[0]; - if (x < minXOffset) { - minXOffset = x; - } else if (x > maxXOffset) { - maxXOffset = x; - } - - var y = offsets[1]; - if (y < minYOffset) { - minYOffset = y; - } else if (y > maxYOffset) { - maxYOffset = y; - } - } - - /* - * Prevents offsets from being decimal or NaN - * See https://github.com/snowplow/snowplow-javascript-tracker/issues/324 - * TODO: the NaN check should be moved into the core - */ - function cleanOffset(offset) { - var rounded = Math.round(offset); - if (!isNaN(rounded)) { - return rounded; - } - } - - /* - * Sets or renews the session cookie - */ - function setSessionCookie() { - cookie.cookie(getSnowplowCookieName('ses'), '*', configSessionCookieTimeout, configCookiePath, configCookieDomain); - } - - /* - * Sets the Visitor ID cookie: either the first time loadDomainUserIdCookie is called - * or when there is a new visit or a new page view - */ - function setDomainUserIdCookie(_domainUserId, createTs, visitCount, nowTs, lastVisitTs, sessionId) { - cookie.cookie( - getSnowplowCookieName('id'), - _domainUserId + '.' + createTs + '.' + visitCount + '.' + nowTs + '.' + lastVisitTs + '.' + sessionId, - configVisitorCookieTimeout, - configCookiePath, - configCookieDomain); - } - - /** - * Generate a pseudo-unique ID to fingerprint this user - */ - function createNewDomainUserId() { - return uuid.v4(); - } - - /* - * Load the domain user ID and the session ID - * Set the cookies (if cookies are enabled) - */ - function initializeIdsAndCookies() { - var sesCookieSet = configUseCookies && !!getSnowplowCookieValue('ses'); - var idCookieComponents = loadDomainUserIdCookie(); - - if (idCookieComponents[1]) { - domainUserId = idCookieComponents[1]; - } else { - domainUserId = createNewDomainUserId(); - idCookieComponents[1] = domainUserId; - } - - memorizedSessionId = idCookieComponents[6]; - - if (!sesCookieSet) { - - // Increment the session ID - idCookieComponents[3] ++; - - // Create a new sessionId - memorizedSessionId = uuid.v4(); - idCookieComponents[6] = memorizedSessionId; - // Set lastVisitTs to currentVisitTs - idCookieComponents[5] = idCookieComponents[4]; - } - - if (configUseCookies) { - setSessionCookie(); - // Update currentVisitTs - idCookieComponents[4] = Math.round(new Date().getTime() / 1000); - idCookieComponents.shift(); - setDomainUserIdCookie.apply(null, idCookieComponents); - } - } - - /* - * Load visitor ID cookie - */ - function loadDomainUserIdCookie() { - if (!configUseCookies) { - return []; - } - var now = new Date(), - nowTs = Math.round(now.getTime() / 1000), - id = getSnowplowCookieValue('id'), - tmpContainer; - - if (id) { - tmpContainer = id.split('.'); - // New visitor set to 0 now - tmpContainer.unshift('0'); - } else { - - tmpContainer = [ - // New visitor - '1', - // Domain user ID - domainUserId, - // Creation timestamp - seconds since Unix epoch - nowTs, - // visitCount - 0 = no previous visit - 0, - // Current visit timestamp - nowTs, - // Last visit timestamp - blank meaning no previous visit - '' - ]; - } - - if (!tmpContainer[6]) { - tmpContainer[6] = uuid.v4(); - } - - return tmpContainer; - } - - /* - * Attaches common web fields to every request - * (resolution, url, referrer, etc.) - * Also sets the required cookies. - */ - function addBrowserData(sb) { - var nowTs = Math.round(new Date().getTime() / 1000), - idname = getSnowplowCookieName('id'), - sesname = getSnowplowCookieName('ses'), - ses = getSnowplowCookieValue('ses'), // aka cookie.cookie(sesname) - id = loadDomainUserIdCookie(), - cookiesDisabled = id[0], - _domainUserId = id[1], // We could use the global (domainUserId) but this is better etiquette - createTs = id[2], - visitCount = id[3], - currentVisitTs = id[4], - lastVisitTs = id[5], - sessionIdFromCookie = id[6]; - - if (configDoNotTrack && configUseCookies) { - cookie.cookie(idname, '', -1, configCookiePath, configCookieDomain); - cookie.cookie(sesname, '', -1, configCookiePath, configCookieDomain); - return; - } - - // If cookies are enabled, base visit count and session ID on the cookies - if (cookiesDisabled === '0') { - memorizedSessionId = sessionIdFromCookie; - - // New session? - if (!ses && configUseCookies) { - // New session (aka new visit) - visitCount++; - // Update the last visit timestamp - lastVisitTs = currentVisitTs; - // Regenerate the session ID - memorizedSessionId = uuid.v4(); - } - - memorizedVisitCount = visitCount; - - // Otherwise, a new session starts if configSessionCookieTimeout seconds have passed since the last event - } else { - if ((new Date().getTime() - lastEventTime) > configSessionCookieTimeout * 1000) { - memorizedSessionId = uuid.v4(); - memorizedVisitCount++; - } - } - - // Build out the rest of the request - sb.add('vp', detectors.detectViewport()); - sb.add('ds', detectors.detectDocumentSize()); - sb.add('vid', memorizedVisitCount); - sb.add('sid', memorizedSessionId); - sb.add('duid', _domainUserId); // Set to our local variable - sb.add('fp', userFingerprint); - sb.add('uid', businessUserId); - - refreshUrl(); - - sb.add('refr', purify(customReferrer || configReferrerUrl)); - - // Add the page URL last as it may take us over the IE limit (and we don't always need it) - sb.add('url', purify(configCustomUrl || locationHrefAlias)); - - // Update cookies - if (configUseCookies) { - setDomainUserIdCookie(_domainUserId, createTs, memorizedVisitCount, nowTs, lastVisitTs, memorizedSessionId); - setSessionCookie(); - } - - lastEventTime = new Date().getTime(); - } - - /** - * Builds a collector URL from a CloudFront distribution. - * We don't bother to support custom CNAMEs because Amazon CloudFront doesn't support that for SSL. - * - * @param string account The account ID to build the tracker URL from - * - * @return string The URL on which the collector is hosted - */ - function collectorUrlFromCfDist(distSubdomain) { - return asCollectorUrl(distSubdomain + '.cloudfront.net'); - } - /** * Adds the protocol in front of our collector URL, and i to the end * @@ -739,889 +144,47 @@ return ('https:' === documentAlias.location.protocol ? 'https' : 'http') + '://' + rawUrl; } - /** - * Add common contexts to every event - * TODO: move this functionality into the core - * - * @param array userContexts List of user-defined contexts - * @return userContexts combined with commonContexts - */ - function addCommonContexts(userContexts) { - var combinedContexts = commonContexts.concat(userContexts || []); - // Add PerformanceTiming Context - if (autoContexts.performanceTiming) { - var performanceTimingContext = getPerformanceTimingContext(); - if (performanceTimingContext) { - combinedContexts.push(performanceTimingContext); - } - } - // Add Optimizely Contexts - if (window['optimizely']) { + /************************************************************ + * Constructor + ************************************************************/ - if (autoContexts.optimizelyExperiments) { - var experimentContexts = getOptimizelyExperimentContexts(); - for (var i = 0; i < experimentContexts.length; i++) { - combinedContexts.push(experimentContexts[i]); - } - } + /* + * Initialize tracker + */ - if (autoContexts.optimizelyStates) { - var stateContexts = getOptimizelyStateContexts(); - for (var i = 0; i < stateContexts.length; i++) { - combinedContexts.push(stateContexts[i]); - } - } - if (autoContexts.optimizelyVariations) { - var variationContexts = getOptimizelyVariationContexts(); - for (var i = 0; i < variationContexts.length; i++) { - combinedContexts.push(variationContexts[i]); - } - } + /************************************************************ + * Public data and methods + ************************************************************/ - if (autoContexts.optimizelyVisitor) { - var optimizelyVisitorContext = getOptimizelyVisitorContext(); - if (optimizelyVisitorContext) { - combinedContexts.push(optimizelyVisitorContext); - } - } + return { - if (autoContexts.optimizelyAudiences) { - var audienceContexts = getOptimizelyAudienceContexts(); - for (var i = 0; i < audienceContexts.length; i++) { - combinedContexts.push(audienceContexts[i]); - } - } - if (autoContexts.optimizelyDimensions) { - var dimensionContexts = getOptimizelyDimensionContexts(); - for (var i = 0; i < dimensionContexts.length; i++) { - combinedContexts.push(dimensionContexts[i]); - } - } - } + /** + * Prevent tracking if user's browser has Do Not Track feature enabled, + * where tracking is: + * 1) Sending events to a collector + * 2) Setting first-party cookies + * @param bool enable If true and Do Not Track feature enabled, don't track. + */ + respectDoNotTrack: function (enable) { + var dnt = navigatorAlias.doNotTrack || navigatorAlias.msDoNotTrack; - // Add Augur Context - if (autoContexts.augurIdentityLite) { - var augurIdentityLiteContext = getAugurIdentityLiteContext(); - if (augurIdentityLiteContext) { - combinedContexts.push(augurIdentityLiteContext); - } - } + configDoNotTrack = enable && (dnt === 'yes' || dnt === '1'); + }, - return combinedContexts; - } - /** - * Put together a web page context with a unique UUID for the page view - * - * @return object web_page context - */ - function getWebPageContext() { - return { - schema: 'iglu:com.snowplowanalytics.snowplow/web_page/jsonschema/1-0-0', - data: { - id: pageViewId + + /** + * Frame buster + */ + killFrame: function () { + if (windowAlias.location !== windowAlias.top.location) { + windowAlias.top.location = windowAlias.location; } - }; - } - - /** - * Creates a context from the window.performance.timing object - * - * @return object PerformanceTiming context - */ - function getPerformanceTimingContext() { - var allowedKeys = [ - 'navigationStart', 'redirectStart', 'redirectEnd', 'fetchStart', 'domainLookupStart', 'domainLookupEnd', 'connectStart', - 'secureConnectionStart', 'connectEnd', 'requestStart', 'responseStart', 'responseEnd', 'unloadEventStart', 'unloadEventEnd', - 'domLoading', 'domInteractive', 'domContentLoadedEventStart', 'domContentLoadedEventEnd', 'domComplete', 'loadEventStart', - 'loadEventEnd', 'msFirstPaint', 'chromeFirstPaint', 'requestEnd', 'proxyStart', 'proxyEnd' - ]; - var performance = windowAlias.performance || windowAlias.mozPerformance || windowAlias.msPerformance || windowAlias.webkitPerformance; - if (performance) { - - // On Safari, the fields we are interested in are on the prototype chain of - // performance.timing so we cannot copy them using lodash.clone - var performanceTiming = {}; - for (var field in performance.timing) { - if (helpers.isValueInArray(field, allowedKeys)) { - performanceTiming[field] = performance.timing[field]; - } - } - - // Old Chrome versions add an unwanted requestEnd field - delete performanceTiming.requestEnd; - - // Add the Chrome firstPaintTime to the performance if it exists - if (windowAlias.chrome && windowAlias.chrome.loadTimes && typeof windowAlias.chrome.loadTimes().firstPaintTime === 'number') { - performanceTiming.chromeFirstPaint = Math.round(windowAlias.chrome.loadTimes().firstPaintTime * 1000); - } - - return { - schema: 'iglu:org.w3/PerformanceTiming/jsonschema/1-0-0', - data: performanceTiming - }; - } - } - - /** - * Creates a context from the window['optimizely'].data.experiments object - * - * @return array Experiment contexts - */ - function getOptimizelyExperimentContexts() { - var experiments = window['optimizely'].data.experiments; - if (experiments) { - var contexts = []; - - for (var key in experiments) { - if (experiments.hasOwnProperty(key)) { - var context = {}; - context['id'] = key; - var experiment = experiments[key]; - context['code'] = experiment.code; - context['manual'] = experiment.manual; - context['conditional'] = experiment.conditional; - context['name'] = experiment.name; - context['variationIds'] = experiment.variation_ids; - - contexts.push({ - schema: 'iglu:com.optimizely/experiment/jsonschema/1-0-0', - data: context - }); - } - } - return contexts; - } - return []; - } - - /** - * Creates a context from the window['optimizely'].data.state object - * - * @return array State contexts - */ - function getOptimizelyStateContexts() { - var experimentIds = []; - var experiments = window['optimizely'].data.experiments; - if (experiments) { - for (var key in experiments) { - if (experiments.hasOwnProperty(key)) { - experimentIds.push(key); - } - } - } - - var state = window['optimizely'].data.state; - if (state) { - var contexts = []; - var activeExperiments = state.activeExperiments || []; - - for (var i = 0; i < experimentIds.length; i++) { - var experimentId = experimentIds[i]; - var context = {}; - context['experimentId'] = experimentId; - context['isActive'] = helpers.isValueInArray(experimentIds[i], activeExperiments); - var variationMap = state.variationMap || {}; - context['variationIndex'] = variationMap[experimentId]; - var variationNamesMap = state.variationNamesMap || {}; - context['variationName'] = variationNamesMap[experimentId]; - var variationIdsMap = state.variationIdsMap || {}; - if (variationIdsMap[experimentId] && variationIdsMap[experimentId].length === 1) { - context['variationId'] = variationIdsMap[experimentId][0]; - } - - contexts.push({ - schema: 'iglu:com.optimizely/state/jsonschema/1-0-0', - data: context - }); - } - return contexts; - } - return []; - } - - /** - * Creates a context from the window['optimizely'].data.variations object - * - * @return array Variation contexts - */ - function getOptimizelyVariationContexts() { - var variations = window['optimizely'].data.variations; - if (variations) { - var contexts = []; - - for (var key in variations) { - if (variations.hasOwnProperty(key)) { - var context = {}; - context['id'] = key; - var variation = variations[key]; - context['name'] = variation.name; - context['code'] = variation.code; - - contexts.push({ - schema: 'iglu:com.optimizely/variation/jsonschema/1-0-0', - data: context - }); - } - } - return contexts; - } - return []; - } - - /** - * Creates a context from the window['optimizely'].data.visitor object - * - * @return object Visitor context - */ - function getOptimizelyVisitorContext() { - var visitor = window['optimizely'].data.visitor; - if (visitor) { - var context = {}; - context['browser'] = visitor.browser; - context['browserVersion'] = visitor.browserVersion; - context['device'] = visitor.device; - context['deviceType'] = visitor.deviceType; - context['ip'] = visitor.ip; - var platform = visitor.platform || {}; - context['platformId'] = platform.id; - context['platformVersion'] = platform.version; - var location = visitor.location || {}; - context['locationCity'] = location.city; - context['locationRegion'] = location.region; - context['locationCountry'] = location.country; - context['mobile'] = visitor.mobile; - context['mobileId'] = visitor.mobileId; - context['referrer'] = visitor.referrer; - context['os'] = visitor.os; - - return { - schema: 'iglu:com.optimizely/visitor/jsonschema/1-0-0', - data: context - }; - } - } - - /** - * Creates a context from the window['optimizely'].data.visitor.audiences object - * - * @return array VisitorAudience contexts - */ - function getOptimizelyAudienceContexts() { - var audienceIds = window['optimizely'].data.visitor.audiences; - if (audienceIds) { - var contexts = []; - - for (var key in audienceIds) { - if (audienceIds.hasOwnProperty(key)) { - var context = {}; - context['id'] = key; - context['isMember'] = audienceIds[key]; - - contexts.push({ - schema: 'iglu:com.optimizely/visitor_audience/jsonschema/1-0-0', - data: context - }); - } - } - return contexts; - } - return []; - } - - /** - * Creates a context from the window['optimizely'].data.visitor.dimensions object - * - * @return array VisitorDimension contexts - */ - function getOptimizelyDimensionContexts() { - var dimensionIds = window['optimizely'].data.visitor.dimensions; - if (dimensionIds) { - var contexts = []; - - for (var key in dimensionIds) { - if (dimensionIds.hasOwnProperty(key)) { - var context = {}; - context['id'] = key; - context['value'] = dimensionIds[key]; - - contexts.push({ - schema: 'iglu:com.optimizely/visitor_dimension/jsonschema/1-0-0', - data: context - }); - } - } - return contexts; - } - return []; - } - - /** - * Creates a context from the window['augur'] object - * - * @return object The IdentityLite context - */ - function getAugurIdentityLiteContext() { - var augur = window['augur']; - if (augur) { - var context = { consumer: {}, device: {} }; - var consumer = augur.consumer || {}; - context['consumer']['UUID'] = consumer.UID; - var device = augur.device || {}; - context['device']['ID'] = device.ID; - context['device']['isBot'] = device.isBot; - context['device']['isProxied'] = device.isProxied; - context['device']['isTor'] = device.isTor; - var fingerprint = device.fingerprint || {}; - context['device']['isIncognito'] = fingerprint.browserHasIncognitoEnabled; - - return { - schema: 'iglu:io.augur.snowplow/identity_lite/jsonschema/1-0-0', - data: context - }; - } - } - - /** - * Attempts to create a context using the geolocation API and add it to commonContexts - */ - function enableGeolocationContext() { - if (!geolocationContextAdded && navigatorAlias.geolocation && navigatorAlias.geolocation.getCurrentPosition) { - geolocationContextAdded = true; - navigator.geolocation.getCurrentPosition(function (position) { - var coords = position.coords; - var geolocationContext = { - schema: 'iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0', - data: { - latitude: coords.latitude, - longitude: coords.longitude, - latitudeLongitudeAccuracy: coords.accuracy, - altitude: coords.altitude, - altitudeAccuracy: coords.altitudeAccuracy, - bearing: coords.heading, - speed: coords.speed, - timestamp: position.timestamp - } - }; - commonContexts.push(geolocationContext); - }); - } - } - - /** - * Creates a context containing the values of the cookies set by GA - * - * @return object GA cookies context - */ - function getGaCookiesContext() { - var gaCookieData = {}; - lodash.forEach(['__utma', '__utmb', '__utmc', '__utmv', '__utmz', '_ga'], function (cookieType) { - var value = cookie.cookie(cookieType); - if (value) { - gaCookieData[cookieType] = value; - } - }); - return { - schema: 'iglu:com.google.analytics/cookies/jsonschema/1-0-0', - data: gaCookieData - }; - } - - /** - * Combine an array of unchanging contexts with the result of a context-creating function - * - * @param object staticContexts Array of custom contexts - * @param object contextCallback Function returning an array of contexts - */ - function finalizeContexts(staticContexts, contextCallback) { - return (staticContexts || []).concat(contextCallback ? contextCallback() : []); - } - - /** - * Log the page view / visit - * - * @param string customTitle The user-defined page title to attach to this page view - * @param object context Custom context relating to the event - * @param object contextCallback Function returning an array of contexts - */ - function logPageView(customTitle, context, contextCallback) { - - refreshUrl(); - - // So we know what document.title was at the time of trackPageView - lastDocumentTitle = documentAlias.title; - lastConfigTitle = customTitle; - - // Fixup page title - var pageTitle = helpers.fixupTitle(lastConfigTitle || lastDocumentTitle); - - // Log page view - core.trackPageView( - purify(configCustomUrl || locationHrefAlias), - pageTitle, - purify(customReferrer || configReferrerUrl), - addCommonContexts(finalizeContexts(context, contextCallback))); - - // Send ping (to log that user has stayed on page) - var now = new Date(); - if (configMinimumVisitTime && configHeartBeatTimer && !activityTrackingInstalled) { - activityTrackingInstalled = true; - - // Capture our initial scroll points - resetMaxScrolls(); - - // Add event handlers; cross-browser compatibility here varies significantly - // @see http://quirksmode.org/dom/events - helpers.addEventListener(documentAlias, 'click', activityHandler); - helpers.addEventListener(documentAlias, 'mouseup', activityHandler); - helpers.addEventListener(documentAlias, 'mousedown', activityHandler); - helpers.addEventListener(documentAlias, 'mousemove', activityHandler); - helpers.addEventListener(documentAlias, 'mousewheel', activityHandler); - helpers.addEventListener(windowAlias, 'DOMMouseScroll', activityHandler); - helpers.addEventListener(windowAlias, 'scroll', scrollHandler); // Will updateMaxScrolls() for us - helpers.addEventListener(documentAlias, 'keypress', activityHandler); - helpers.addEventListener(documentAlias, 'keydown', activityHandler); - helpers.addEventListener(documentAlias, 'keyup', activityHandler); - helpers.addEventListener(windowAlias, 'resize', activityHandler); - helpers.addEventListener(windowAlias, 'focus', activityHandler); - helpers.addEventListener(windowAlias, 'blur', activityHandler); - - // Periodic check for activity. - lastActivityTime = now.getTime(); - setInterval(function heartBeat() { - var now = new Date(); - - // There was activity during the heart beat period; - // on average, this is going to overstate the visitDuration by configHeartBeatTimer/2 - if ((lastActivityTime + configHeartBeatTimer) > now.getTime()) { - // Send ping if minimum visit time has elapsed - if (configMinimumVisitTime < now.getTime()) { - logPagePing(finalizeContexts(context, contextCallback)); // Grab the min/max globals - } - } - }, configHeartBeatTimer); - } - } - - /** - * Log that a user is still viewing a given page - * by sending a page ping. - * Not part of the public API - only called from - * logPageView() above. - * - * @param object context Custom context relating to the event - */ - function logPagePing(context) { - refreshUrl(); - newDocumentTitle = documentAlias.title; - if (newDocumentTitle !== lastDocumentTitle) { - lastDocumentTitle = newDocumentTitle; - lastConfigTitle = null; - } - core.trackPagePing( - purify(configCustomUrl || locationHrefAlias), - helpers.fixupTitle(lastConfigTitle || lastDocumentTitle), - purify(customReferrer || configReferrerUrl), - cleanOffset(minXOffset), - cleanOffset(maxXOffset), - cleanOffset(minYOffset), - cleanOffset(maxYOffset), - addCommonContexts(context)); - resetMaxScrolls(); - } - - /** - * Log ecommerce transaction metadata - * - * @param string orderId - * @param string affiliation - * @param string total - * @param string tax - * @param string shipping - * @param string city - * @param string state - * @param string country - * @param string currency The currency the total/tax/shipping are expressed in - * @param object context Custom context relating to the event - */ - function logTransaction(orderId, affiliation, total, tax, shipping, city, state, country, currency, context) { - core.trackEcommerceTransaction(orderId, affiliation, total, tax, shipping, city, state, country, currency, addCommonContexts(context)); - } - - /** - * Log ecommerce transaction item - * - * @param string orderId - * @param string sku - * @param string name - * @param string category - * @param string price - * @param string quantity - * @param string currency The currency the price is expressed in - * @param object context Custom context relating to the event - */ - function logTransactionItem(orderId, sku, name, category, price, quantity, currency, context) { - core.trackEcommerceTransactionItem(orderId, sku, name, category, price, quantity, currency, addCommonContexts(context)); - } - - /* - * Browser prefix - */ - function prefixPropertyName(prefix, propertyName) { - - if (prefix !== '') { - return prefix + propertyName.charAt(0).toUpperCase() + propertyName.slice(1); - } - - return propertyName; - } - - /** - * Check for pre-rendered web pages, and log the page view/link - * according to the configuration and/or visibility - * - * @see http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html - */ - function trackCallback(callback) { - var isPreRendered, - i, - // Chrome 13, IE10, FF10 - prefixes = ['', 'webkit', 'ms', 'moz'], - prefix; - - if (!configCountPreRendered) { - for (i = 0; i < prefixes.length; i++) { - prefix = prefixes[i]; - - // does this browser support the page visibility API? - if (documentAlias[prefixPropertyName(prefix, 'hidden')]) { - // if pre-rendered, then defer callback until page visibility changes - if (documentAlias[prefixPropertyName(prefix, 'visibilityState')] === 'prerender') { - isPreRendered = true; - } - break; - } - } - } - - if (isPreRendered) { - // note: the event name doesn't follow the same naming convention as vendor properties - helpers.addEventListener(documentAlias, prefix + 'visibilitychange', function ready() { - documentAlias.removeEventListener(prefix + 'visibilitychange', ready, false); - callback(); - }); - return; - } - - // configCountPreRendered === true || isPreRendered === false - callback(); - } - - - /************************************************************ - * Constructor - ************************************************************/ - - /* - * Initialize tracker - */ - updateDomainHash(); - - initializeIdsAndCookies(); - - if (argmap.crossDomainLinker) { - decorateLinks(argmap.crossDomainLinker); - } - - /************************************************************ - * Public data and methods - ************************************************************/ - - return { - - /** - * Get the current user ID (as set previously - * with setUserId()). - * - * @return string Business-defined user ID - */ - getUserId: function () { - return businessUserId; - }, - - /** - * Get visitor ID (from first party cookie) - * - * @return string Visitor ID in hexits (or null, if not yet known) - */ - getDomainUserId: function () { - return (loadDomainUserIdCookie())[1]; - }, - - /** - * Get the visitor information (from first party cookie) - * - * @return array - */ - getDomainUserInfo: function () { - return loadDomainUserIdCookie(); - }, - - /** - * Get the user fingerprint - * - * @return string The user fingerprint - */ - getUserFingerprint: function () { - return userFingerprint; - }, - - /** - * Specify the app ID - * - * @param int|string appId - */ - setAppId: function (appId) { - helpers.warn('setAppId is deprecated. Instead add an "appId" field to the argmap argument of newTracker.'); - core.setAppId(appId); - }, - - /** - * Override referrer - * - * @param string url - */ - setReferrerUrl: function (url) { - customReferrer = url; - }, - - /** - * Override url - * - * @param string url - */ - setCustomUrl: function (url) { - refreshUrl(); - configCustomUrl = resolveRelativeReference(locationHrefAlias, url); - }, - - /** - * Override document.title - * - * @param string title - */ - setDocumentTitle: function (title) { - // So we know what document.title was at the time of trackPageView - lastDocumentTitle = documentAlias.title; - lastConfigTitle = title; - }, - - /** - * Strip hash tag (or anchor) from URL - * - * @param bool enableFilter - */ - discardHashTag: function (enableFilter) { - configDiscardHashTag = enableFilter; - }, - - /** - * Set first-party cookie name prefix - * - * @param string cookieNamePrefix - */ - setCookieNamePrefix: function (cookieNamePrefix) { - helpers.warn('setCookieNamePrefix is deprecated. Instead add a "cookieName" field to the argmap argument of newTracker.'); - configCookieNamePrefix = cookieNamePrefix; - }, - - /** - * Set first-party cookie domain - * - * @param string domain - */ - setCookieDomain: function (domain) { - helpers.warn('setCookieDomain is deprecated. Instead add a "cookieDomain" field to the argmap argument of newTracker.'); - configCookieDomain = helpers.fixupDomain(domain); - updateDomainHash(); - }, - - /** - * Set first-party cookie path - * - * @param string domain - */ - setCookiePath: function (path) { - configCookiePath = path; - updateDomainHash(); - }, - - /** - * Set visitor cookie timeout (in seconds) - * - * @param int timeout - */ - setVisitorCookieTimeout: function (timeout) { - configVisitorCookieTimeout = timeout; - }, - - /** - * Set session cookie timeout (in seconds) - * - * @param int timeout - */ - setSessionCookieTimeout: function (timeout) { - helpers.warn('setSessionCookieTimeout is deprecated. Instead add a "sessionCookieTimeout" field to the argmap argument of newTracker.') - configSessionCookieTimeout = timeout; - }, - - /** - * @param number seed The seed used for MurmurHash3 - */ - setUserFingerprintSeed: function(seed) { - helpers.warn('setUserFingerprintSeed is deprecated. Instead add a "userFingerprintSeed" field to the argmap argument of newTracker.'); - configUserFingerprintHashSeed = seed; - userFingerprint = detectors.detectSignature(configUserFingerprintHashSeed); - }, - - /** - * Enable/disable user fingerprinting. User fingerprinting is enabled by default. - * @param bool enable If false, turn off user fingerprinting - */ - enableUserFingerprint: function(enable) { - helpers.warn('enableUserFingerprintSeed is deprecated. Instead add a "userFingerprint" field to the argmap argument of newTracker.'); - if (!enable) { - userFingerprint = ''; - } - }, - - /** - * Prevent tracking if user's browser has Do Not Track feature enabled, - * where tracking is: - * 1) Sending events to a collector - * 2) Setting first-party cookies - * @param bool enable If true and Do Not Track feature enabled, don't track. - */ - respectDoNotTrack: function (enable) { - helpers.warn('This usage of respectDoNotTrack is deprecated. Instead add a "respectDoNotTrack" field to the argmap argument of newTracker.'); - var dnt = navigatorAlias.doNotTrack || navigatorAlias.msDoNotTrack; - - configDoNotTrack = enable && (dnt === 'yes' || dnt === '1'); - }, - - /** - * Enable querystring decoration for links pasing a filter - * - * @param function crossDomainLinker Function used to determine which links to decorate - */ - crossDomainLinker: function (crossDomainLinkerCriterion) { - decorateLinks(crossDomainLinkerCriterion); - }, - - /** - * Add click listener to a specific link element. - * When clicked, Piwik will log the click automatically. - * - * @param DOMElement element - * @param bool enable If true, use pseudo click-handler (mousedown+mouseup) - */ - addListener: function (element, pseudoClicks, context) { - addClickListener(element, pseudoClicks, context); - }, - - /** - * Install link tracker - * - * The default behaviour is to use actual click events. However, some browsers - * (e.g., Firefox, Opera, and Konqueror) don't generate click events for the middle mouse button. - * - * To capture more "clicks", the pseudo click-handler uses mousedown + mouseup events. - * This is not industry standard and is vulnerable to false positives (e.g., drag events). - * - * There is a Safari/Chrome/Webkit bug that prevents tracking requests from being sent - * by either click handler. The workaround is to set a target attribute (which can't - * be "_self", "_top", or "_parent"). - * - * @see https://bugs.webkit.org/show_bug.cgi?id=54783 - * - * @param object criterion Criterion by which it will be decided whether a link will be tracked - * @param bool pseudoClicks If true, use pseudo click-handler (mousedown+mouseup) - * @param bool trackContent Whether to track the innerHTML of the link element - * @param array context Context for all link click events - */ - enableLinkClickTracking: function (criterion, pseudoClicks, trackContent, context) { - if (mutSnowplowState.hasLoaded) { - // the load event has already fired, add the click listeners now - linkTrackingManager.configureLinkClickTracking(criterion, pseudoClicks, trackContent, context); - linkTrackingManager.addClickListeners(); - } else { - // defer until page has loaded - mutSnowplowState.registeredOnLoadHandlers.push(function () { - linkTrackingManager.configureLinkClickTracking(criterion, pseudoClicks, trackContent, context); - linkTrackingManager.addClickListeners(); - }); - } - }, - - /** - * Add click event listeners to links which have been added to the page since the - * last time enableLinkClickTracking or refreshLinkClickTracking was used - */ - refreshLinkClickTracking: function () { - if (mutSnowplowState.hasLoaded) { - linkTrackingManager.addClickListeners(); - } else { - mutSnowplowState.registeredOnLoadHandlers.push(function () { - linkTrackingManager.addClickListeners(); - }); - } - }, - - /** - * Enables page activity tracking (sends page - * pings to the Collector regularly). - * - * @param int minimumVisitLength Seconds to wait before sending first page ping - * @param int heartBeatDelay Seconds to wait between pings - */ - enableActivityTracking: function (minimumVisitLength, heartBeatDelay) { - configMinimumVisitTime = new Date().getTime() + minimumVisitLength * 1000; - configHeartBeatTimer = heartBeatDelay * 1000; - }, - - /** - * Enables automatic form tracking. - * An event will be fired when a form field is changed or a form submitted. - * This can be called multiple times: only forms not already tracked will be tracked. - * - * @param object config Configuration object determining which forms and fields to track. - * Has two properties: "forms" and "fields" - * @param array context Context for all form tracking events - */ - enableFormTracking: function (config, context) { - if (mutSnowplowState.hasLoaded) { - formTrackingManager.configureFormTracking(config); - formTrackingManager.addFormListeners(context); - } else { - mutSnowplowState.registeredOnLoadHandlers.push(function () { - formTrackingManager.configureFormTracking(config); - formTrackingManager.addFormListeners(context); - }); - } - }, - - /** - * Frame buster - */ - killFrame: function () { - if (windowAlias.location !== windowAlias.top.location) { - windowAlias.top.location = windowAlias.location; - } - }, + }, /** * Redirect if browsing offline (aka file: buster) @@ -1634,61 +197,17 @@ } }, - /** - * Count sites in pre-rendered state - * - * @param bool enable If true, track when in pre-rendered state - */ - setCountPreRendered: function (enable) { - configCountPreRendered = enable; - }, - /** - * Set the business-defined user ID for this user. - * - * @param string userId The business-defined user ID - */ - setUserId: function(userId) { - businessUserId = userId; - }, /** - * Set the business-defined user ID for this user using the location querystring. - * - * @param string queryName Name of a querystring name-value pair - */ - setUserIdFromLocation: function(querystringField) { - refreshUrl(); - businessUserId = helpers.fromQuerystring(querystringField, locationHrefAlias); - }, - - /** - * Set the business-defined user ID for this user using the referrer querystring. - * - * @param string queryName Name of a querystring name-value pair + * Send all events in the outQueue + * Use only when sending POSTs with a bufferSize of at least 2 */ - setUserIdFromReferrer: function(querystringField) { - refreshUrl(); - businessUserId = helpers.fromQuerystring(querystringField, configReferrerUrl); + flushBuffer: function () { + outQueueManager.executeQueue(configUseSecureCredentials,configCollectorToken); }, - /** - * Set the business-defined user ID for this user to the value of a cookie. - * - * @param string cookieName Name of the cookie whose value will be assigned to businessUserId - */ - setUserIdFromCookie: function(cookieName) { - businessUserId = cookie.cookie(cookieName); - }, - /** - * Configure this tracker to log to a CloudFront collector. - * - * @param string distSubdomain The subdomain on your CloudFront collector's distribution - */ - setCollectorCf: function (distSubdomain) { - configCollectorUrl = collectorUrlFromCfDist(distSubdomain); - }, /** * @@ -1701,453 +220,17 @@ configCollectorUrl = asCollectorUrl(rawUrl); }, - /** - * Specify the platform - * - * @param string platform Overrides the default tracking platform - */ - setPlatform: function(platform) { - helpers.warn('setPlatform is deprecated. Instead add a "platform" field to the argmap argument of newTracker.'); - core.setPlatform(platform); - }, - - /** - * - * Enable Base64 encoding for unstructured event payload - * - * @param bool enabled A boolean value indicating if the Base64 encoding for unstructured events should be enabled or not - */ - encodeBase64: function (enabled) { - helpers.warn('This usage of encodeBase64 is deprecated. Instead add an "encodeBase64" field to the argmap argument of newTracker.'); - core.setBase64Encoding(enabled); - }, - - /** - * Send all events in the outQueue - * Use only when sending POSTs with a bufferSize of at least 2 - */ - flushBuffer: function () { - outQueueManager.executeQueue(); - }, - - /** - * Add the geolocation context to all events - */ - enableGeolocationContext: enableGeolocationContext, - - /** - * Log visit to this page - * - * @param string customTitle - * @param object Custom context relating to the event - * @param object contextCallback Function returning an array of contexts - */ - trackPageView: function (customTitle, context, contextCallback) { - trackCallback(function () { - logPageView(customTitle, context, contextCallback); - }); - }, - - /** - * Track a structured event happening on this page. - * - * Replaces trackEvent, making clear that the type - * of event being tracked is a structured one. - * - * @param string category The name you supply for the group of objects you want to track - * @param string action A string that is uniquely paired with each category, and commonly used to define the type of user interaction for the web object - * @param string label (optional) An optional string to provide additional dimensions to the event data - * @param string property (optional) Describes the object or the action performed on it, e.g. quantity of item added to basket - * @param int|float|string value (optional) An integer that you can use to provide numerical data about the user event - * @param object Custom context relating to the event - */ - trackStructEvent: function (category, action, label, property, value, context) { - core.trackStructEvent(category, action, label, property, value, addCommonContexts(context)); - }, - /** * Track an unstructured event happening on this page. * * @param object eventJson Contains the properties and schema location for the event - * @param object context Custom context relating to the event - */ - trackUnstructEvent: function (eventJson, context) { - core.trackUnstructEvent(eventJson, addCommonContexts(context)); - }, - - /** - * Track an ecommerce transaction - * - * @param string orderId Required. Internal unique order id number for this transaction. - * @param string affiliation Optional. Partner or store affiliation. - * @param string total Required. Total amount of the transaction. - * @param string tax Optional. Tax amount of the transaction. - * @param string shipping Optional. Shipping charge for the transaction. - * @param string city Optional. City to associate with transaction. - * @param string state Optional. State to associate with transaction. - * @param string country Optional. Country to associate with transaction. - * @param string currency Optional. Currency to associate with this transaction. - * @param object context Optional. Context relating to the event. - */ - addTrans: function(orderId, affiliation, total, tax, shipping, city, state, country, currency, context) { - ecommerceTransaction.transaction = { - orderId: orderId, - affiliation: affiliation, - total: total, - tax: tax, - shipping: shipping, - city: city, - state: state, - country: country, - currency: currency, - context: context - }; - }, - - /** - * Track an ecommerce transaction item - * - * @param string orderId Required Order ID of the transaction to associate with item. - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string price Required. Product price. - * @param string quantity Required. Purchase quantity. - * @param string currency Optional. Product price currency. - * @param object context Optional. Context relating to the event. - */ - addItem: function(orderId, sku, name, category, price, quantity, currency, context) { - ecommerceTransaction.items.push({ - orderId: orderId, - sku: sku, - name: name, - category: category, - price: price, - quantity: quantity, - currency: currency, - context: context - }); - }, - - /** - * Commit the ecommerce transaction - * - * This call will send the data specified with addTrans, - * addItem methods to the tracking server. */ - trackTrans: function() { - logTransaction( - ecommerceTransaction.transaction.orderId, - ecommerceTransaction.transaction.affiliation, - ecommerceTransaction.transaction.total, - ecommerceTransaction.transaction.tax, - ecommerceTransaction.transaction.shipping, - ecommerceTransaction.transaction.city, - ecommerceTransaction.transaction.state, - ecommerceTransaction.transaction.country, - ecommerceTransaction.transaction.currency, - ecommerceTransaction.transaction.context - ); - for (var i = 0; i < ecommerceTransaction.items.length; i++) { - var item = ecommerceTransaction.items[i]; - logTransactionItem( - item.orderId, - item.sku, - item.name, - item.category, - item.price, - item.quantity, - item.currency, - item.context - ); - } - - ecommerceTransaction = ecommerceTransactionTemplate(); - }, - - /** - * Manually log a click from your own code - * - * @param string elementId - * @param array elementClasses - * @param string elementTarget - * @param string targetUrl - * @param string elementContent innerHTML of the element - * @param object Custom context relating to the event - */ - // TODO: break this into trackLink(destUrl) and trackDownload(destUrl) - trackLinkClick: function(targetUrl, elementId, elementClasses, elementTarget, elementContent, context) { - trackCallback(function () { - core.trackLinkClick(targetUrl, elementId, elementClasses, elementTarget, elementContent, addCommonContexts(context)); - }); - }, - - /** - * Track an ad being served - * - * @param string impressionId Identifier for a particular ad impression - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param number cost Cost - * @param string bannerId Identifier for the ad banner displayed - * @param string zoneId Identifier for the ad zone - * @param string advertiserId Identifier for the advertiser - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param object Custom context relating to the event - */ - trackAdImpression: function(impressionId, costModel, cost, targetUrl, bannerId, zoneId, advertiserId, campaignId, context) { - trackCallback(function () { - core.trackAdImpression(impressionId, costModel, cost, targetUrl, bannerId, zoneId, advertiserId, campaignId, addCommonContexts(context)); - }); - }, - - /** - * Track an ad being clicked - * - * @param string clickId Identifier for the ad click - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param number cost Cost - * @param string targetUrl (required) The link's target URL - * @param string bannerId Identifier for the ad banner displayed - * @param string zoneId Identifier for the ad zone - * @param string impressionId Identifier for a particular ad impression - * @param string advertiserId Identifier for the advertiser - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param object Custom context relating to the event - */ - trackAdClick: function(targetUrl, clickId, costModel, cost, bannerId, zoneId, impressionId, advertiserId, campaignId, context) { - core.trackAdClick(targetUrl, clickId, costModel, cost, bannerId, zoneId, impressionId, advertiserId, campaignId, addCommonContexts(context)); - }, - - /** - * Track an ad conversion event - * - * @param string conversionId Identifier for the ad conversion event - * @param number cost Cost - * @param string category The name you supply for the group of objects you want to track - * @param string action A string that is uniquely paired with each category - * @param string property Describes the object of the conversion or the action performed on it - * @param number initialValue Revenue attributable to the conversion at time of conversion - * @param string advertiserId Identifier for the advertiser - * @param string costModel The cost model. 'cpa', 'cpc', or 'cpm' - * @param string campaignId Identifier for the campaign which the banner belongs to - * @param object Custom context relating to the event - */ - trackAdConversion: function(conversionId, costModel, cost, category, action, property, initialValue, advertiserId, campaignId, context) { - core.trackAdConversion(conversionId, costModel, cost, category, action, property, initialValue, advertiserId, campaignId, addCommonContexts(context)); - }, - - /** - * Track a social interaction event - * - * @param string action (required) Social action performed - * @param string network (required) Social network - * @param string target Object of the social action e.g. the video liked, the tweet retweeted - * @param object Custom context relating to the event - */ - trackSocialInteraction: function(action, network, target, context) { - core.trackSocialInteraction(action, network, target, addCommonContexts(context)); - }, - - /** - * Track an add-to-cart event - * - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string unitPrice Optional. Product price. - * @param string quantity Required. Quantity added. - * @param string currency Optional. Product price currency. - * @param array context Optional. Context relating to the event. - */ - trackAddToCart: function(sku, name, category, unitPrice, quantity, currency, context) { - core.trackAddToCart(sku, name, category, unitPrice, quantity, currency, addCommonContexts(context)); - }, - - /** - * Track a remove-from-cart event - * - * @param string sku Required. Item's SKU code. - * @param string name Optional. Product name. - * @param string category Optional. Product category. - * @param string unitPrice Optional. Product price. - * @param string quantity Required. Quantity removed. - * @param string currency Optional. Product price currency. - * @param array context Optional. Context relating to the event. - */ - trackRemoveFromCart: function(sku, name, category, unitPrice, quantity, currency, context) { - core.trackRemoveFromCart(sku, name, category, unitPrice, quantity, currency, addCommonContexts(context)); - }, - - /** - * Track an internal search event - * - * @param array terms Search terms - * @param object filters Search filters - * @param number totalResults Number of results - * @param number pageResults Number of results displayed on page - * @param array context Optional. Context relating to the event. - */ - trackSiteSearch: function(terms, filters, totalResults, pageResults, context) { - core.trackSiteSearch(terms, filters, totalResults, pageResults, addCommonContexts(context)); - }, - - /** - * Track a timing event (such as the time taken for a resource to load) - * - * @param string category Required. - * @param string variable Required. - * @param number timing Required. - * @param string label Optional. - * @param array context Optional. Context relating to the event. - */ - trackTiming: function (category, variable, timing, label, context) { - core.trackUnstructEvent({ - schema: 'iglu:com.snowplowanalytics.snowplow/timing/jsonschema/1-0-0', - data: { - category: category, - variable: variable, - timing: timing, - label: label - } - }, addCommonContexts(context)) - }, - - /** - * Track a GA Enhanced Ecommerce Action with all stored - * Enhanced Ecommerce contexts - * - * @param string action - * @param array context Optional. Context relating to the event. - */ - trackEnhancedEcommerceAction: function (action, context) { - var combinedEnhancedEcommerceContexts = enhancedEcommerceContexts.concat(context || []); - enhancedEcommerceContexts.length = 0; - - core.trackUnstructEvent({ - schema: 'iglu:com.google.analytics.enhanced-ecommerce/action/jsonschema/1-0-0', - data: { - action: action - } - }, addCommonContexts(combinedEnhancedEcommerceContexts)); - }, - - /** - * Adds a GA Enhanced Ecommerce Action Context - * - * @param string id - * @param string affiliation - * @param number revenue - * @param number tax - * @param number shipping - * @param string coupon - * @param string list - * @param integer step - * @param string option - * @param string currency - */ - addEnhancedEcommerceActionContext: function (id, affiliation, revenue, tax, shipping, coupon, list, step, option, currency) { - enhancedEcommerceContexts.push({ - schema: 'iglu:com.google.analytics.enhanced-ecommerce/actionFieldObject/jsonschema/1-0-0', - data: { - id: id, - affiliation: affiliation, - revenue: helpers.parseFloat(revenue), - tax: helpers.parseFloat(tax), - shipping: helpers.parseFloat(shipping), - coupon: coupon, - list: list, - step: helpers.parseInt(step), - option: option, - currency: currency - } - }); - }, - - /** - * Adds a GA Enhanced Ecommerce Impression Context - * - * @param string id - * @param string name - * @param string list - * @param string brand - * @param string category - * @param string variant - * @param integer position - * @param number price - * @param string currency - */ - addEnhancedEcommerceImpressionContext: function (id, name, list, brand, category, variant, position, price, currency) { - enhancedEcommerceContexts.push({ - schema: 'iglu:com.google.analytics.enhanced-ecommerce/impressionFieldObject/jsonschema/1-0-0', - data: { - id: id, - name: name, - list: list, - brand: brand, - category: category, - variant: variant, - position: helpers.parseInt(position), - price: helpers.parseFloat(price), - currency: currency - } - }); + trackUnstructEvent: function (payload) { + sendRequest(payload, configTrackerPause); }, - /** - * Adds a GA Enhanced Ecommerce Product Context - * - * @param string id - * @param string name - * @param string list - * @param string brand - * @param string category - * @param string variant - * @param number price - * @param integer quantity - * @param string coupon - * @param integer position - * @param string currency - */ - addEnhancedEcommerceProductContext: function (id, name, list, brand, category, variant, price, quantity, coupon, position, currency) { - enhancedEcommerceContexts.push({ - schema: 'iglu:com.google.analytics.enhanced-ecommerce/productFieldObject/jsonschema/1-0-0', - data: { - id: id, - name: name, - list: list, - brand: brand, - category: category, - variant: variant, - price: helpers.parseFloat(price), - quantity: helpers.parseInt(quantity), - coupon: coupon, - position: helpers.parseInt(position), - currency: currency - } - }); - }, - /** - * Adds a GA Enhanced Ecommerce Promo Context - * - * @param string id - * @param string name - * @param string creative - * @param string position - * @param string currency - */ - addEnhancedEcommercePromoContext: function (id, name, creative, position, currency) { - enhancedEcommerceContexts.push({ - schema: 'iglu:com.google.analytics.enhanced-ecommerce/promoFieldObject/jsonschema/1-0-0', - data: { - id: id, - name: name, - creative: creative, - position: position, - currency: currency - } - }); - } + }; }; From ab964b1ef287f11b423d11eb0b328eab39fb3cec Mon Sep 17 00:00:00 2001 From: Ilija Ljubicic Date: Thu, 18 Jan 2018 16:14:04 +0200 Subject: [PATCH 2/2] DEPRECATED --- dist/sp100.6.3.js | 39 + npm-shrinkwrap.json | 3951 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 3915 insertions(+), 75 deletions(-) create mode 100644 dist/sp100.6.3.js diff --git a/dist/sp100.6.3.js b/dist/sp100.6.3.js new file mode 100644 index 000000000..6d3e2e3ea --- /dev/null +++ b/dist/sp100.6.3.js @@ -0,0 +1,39 @@ +/*! * Snowplow - The world's most powerful web analytics platform + * + * @description JavaScript tracker for Snowplow + * @version 100.6.3 + * @author Alex Dean, Simon Andersson, Anthon Pang, Fred Blundun, Joshua Beemster + * @copyright Anthon Pang, Snowplow Analytics Ltd + * @license Simplified BSD + */ +(function e(b,g,d){function c(n,j){if(!g[n]){if(!b[n]){var i=typeof require=="function"&&require;if(!j&&i){return i(n,!0)}if(a){return a(n,!0)}var m=new Error("Cannot find module '"+n+"'");throw m.code="MODULE_NOT_FOUND",m}var h=g[n]={exports:{}};b[n][0].call(h.exports,function(l){var o=b[n][1][l];return c(o?o:l)},h,h.exports,e,b,g,d)}return g[n].exports}var a=typeof require=="function"&&require;for(var f=0;f>>(32-g))},rotr:function(h,g){return(h<<(32-g))|(h>>>g)},endian:function(h){if(h.constructor==Number){return f.rotl(h,8)&16711935|f.rotl(h,24)&4278255360}for(var g=0;g0;h--){g.push(Math.floor(Math.random()*256))}return g},bytesToWords:function(h){for(var l=[],j=0,g=0;j>>5]|=h[j]<<(24-g%32)}return l},wordsToBytes:function(i){for(var h=[],g=0; +g>>5]>>>(24-g%32))&255)}return h},bytesToHex:function(g){for(var j=[],h=0;h>>4).toString(16));j.push((g[h]&15).toString(16))}return j.join("")},hexToBytes:function(h){for(var g=[],i=0;i>>6*(3-l))&63))}else{g.push("=")}}}return g.join("")},base64ToBytes:function(h){h=h.replace(/[^A-Z0-9+\/]/ig,"");for(var g=[],j=0,l=0;j>>(6-l*2)))}return g}};c.exports=f})()},{}],4:[function(b,c,a){(function(){var h=b("crypt"),d=b("charenc").utf8,f=b("charenc").bin,i=function(r){if(r.constructor==String){r=d.stringToBytes(r)}var z=h.bytesToWords(r),A=r.length*8,s=[],v=1732584193,u=-271733879,q=-1732584194,p=271733878,o=-1009589776; +z[A>>5]|=128<<(24-A%32);z[((A+64>>>9)<<4)+15]=A;for(var C=0;C>>31)}var x=((v<<5)|(v>>>27))+o+(s[B]>>>0)+(B<20?(u&q|~u&p)+1518500249:B<40?(u^q^p)+1859775393:B<60?(u&q|u&p|q&p)-1894007588:(u^q^p)-899497514);o=p;p=q;q=(u<<30)|(u>>>2);u=v;v=x}v+=H;u+=G;q+=F;p+=E;o+=D}return[v,u,q,p,o]},g=function(m,j){var l=h.wordsToBytes(i(m));return j&&j.asBytes?l:j&&j.asString?f.bytesToString(l):h.bytesToHex(l)};g._blocksize=16;g._digestsize=20;c.exports=g})()},{charenc:2,crypt:3}],5:[function(b,c,a){(function(){var f=b("./lib_managed/lodash"),d=typeof a!=="undefined"?a:this;d.InQueueManager=function(g,n,m,j,o){var h={};function p(u){var v=[];if(!u||u.length===0){v=f.map(h)}else{for(var t=0;t1)?u[1].split(";"):[];return[i,t]}function r(){var v,u,x,w,t,A,y,z;for(v=0;v0){g=c.GlobalSnowplowNamespace.shift();a=c[g];a.q=new h.Snowplow(a.q,g)}else{c._snaq=c._snaq||[];c._snaq=new h.Snowplow(c._snaq,"_snaq")}},{"./snowplow":11}],7:[function(b,c,a){(function(){var f=typeof a!=="undefined"?a:this,d=window,g=navigator,h=screen,i=document;f.hasSessionStorage=function(){try{return !!d.sessionStorage +}catch(j){return true}};f.hasLocalStorage=function(){try{return !!d.localStorage}catch(j){return true}};f.localStorageAccessible=function(){var j="modernizr";if(!f.hasLocalStorage()){return false}try{d.localStorage.setItem(j,j);d.localStorage.removeItem(j);return true}catch(l){return false}}}())},{}],8:[function(b,c,a){(function(){var g=b("../lib_managed/lodash"),d=typeof a!=="undefined"?a:this;d.fixupTitle=function(i){if(!g.isString(i)){i=i.text||"";var h=document.getElementsByTagName("title");if(h&&!g.isUndefined(h[0])){i=h[0].text}}return i};d.getHostName=function(h){var j=new RegExp("^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)"),i=j.exec(h);return i?i[1]:h};d.fixupDomain=function(i){var h=i.length;if(i.charAt(--h)==="."){i=i.slice(0,h)}if(i.slice(0,2)==="*."){i=i.slice(1)}return i};d.addEventListener=function(l,j,i,h){if(l.addEventListener){l.addEventListener(j,i,h);return true}if(l.attachEvent){return l.attachEvent("on"+j,i)}l["on"+j]=i};d.fromQuerystring=function(j,i){var h=new RegExp("^[^#]*[?&]"+j+"=([^&#]*)").exec(i); +if(!h){return null}return decodeURIComponent(h[1].replace(/\+/g," "))};d.warn=function(h){if(typeof console!=="undefined"){}};d.getCssClasses=function(h){return h.className.match(/\S+/g)||[]};function f(h,m){var l=d.getCssClasses(h),j;for(j=0;j=0){var n=m.slice(h,m.length).join(".");cookie.cookie(q,o,0,"/",n);if(cookie.cookie(q)===o){d.deleteCookie(q,n);var p=d.getCookiesWithPrefix(j);for(var l=0;l-1) +}})}}bd.pop();bc.pop();if(a4){az(bd);az(bc)}return a5}function F(aZ,aW,a0,aV,a5,aT){var aY=aW&1,a6=aW&2,a3=aW&4,a2=aW&8,aU=aW&16,a1=aW&32;if(!a6&&!aA(aZ)){throw new TypeError}if(aU&&!a0.length){aW&=~16;aU=a0=false}if(a1&&!aV.length){aW&=~32;a1=aV=false}var aX=aZ&&aZ.__bindData__;if(aX&&aX!==true){aX=z(aX);if(aX[2]){aX[2]=z(aX[2])}if(aX[3]){aX[3]=z(aX[3])}if(aY&&!(aX[1]&1)){aX[4]=a5}if(!aY&&aX[1]&1){aW|=8}if(a3&&!(aX[1]&4)){aX[5]=aT}if(aU){i.apply(aX[2]||(aX[2]=[]),a0)}if(a1){aH.apply(aX[3]||(aX[3]=[]),aV)}aX[1]|=aW;return F.apply(null,aX)}var a4=(aW==1||aW===17)?G:Q;return a4([aZ,aW,a0,aV,a5,aT])}function ar(){U.shadowedProps=K;U.array=U.bottom=U.loop=U.top="";U.init="iterable";U.useHas=true;for(var aW,aV=0;aW=arguments[aV];aV++){for(var aX in aW){U[aX]=aW[aX]}}var aU=U.args;U.firstArg=/^[^,]+/.exec(aU)[0];var aT=Function("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+aU+") {\n"+ab(U)+"\n}"); +return aT(aS,aL,l,ad,aa,g,f,aJ,U.keys,aF,am,au,R,Z,al)}function O(aT){return typeof aT=="function"&&q.test(aT)}var aM=!w?aw:function(aT,aU){aI.value=aU;w(aT,"__bindData__",aI)};function g(aT){return aT&&typeof aT=="object"&&typeof aT.length=="number"&&al.call(aT)==j||false}if(!aG.argsClass){g=function(aT){return aT&&typeof aT=="object"&&typeof aT.length=="number"&&ad.call(aT,"callee")&&!ac.call(aT,"callee")||false}}var f=t||function(aT){return aT&&typeof aT=="object"&&typeof aT.length=="number"&&al.call(aT)==H||false};var V=ar({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"});var J=!aO?V:function(aT){if(!E(aT)){return[]}if((aG.enumPrototypes&&typeof aT=="function")||(aG.nonEnumArgs&&aT.length&&g(aT))){return V(aT)}return aO(aT)};var aK={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:J,loop:"if (callback(iterable[index], index, collection) === false) return result"}; +var I={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",keys:J,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"};var ak={top:"if (!objectTypes[typeof iterable]) return result;\n"+aK.top,array:false};var L=ar(aK);var aC=ar(I,{top:I.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"});function B(aV,aU,aW,aT){if(typeof aU!="boolean"&&aU!=null){aT=aW;aW=aU;aU=false}return ao(aV,aU,typeof aW=="function"&&aS(aW,aT,1))}var ai=ar(aK,ak,{useHas:false}); +var Y=ar(aK,ak);function m(aT){return aT&&typeof aT=="object"&&al.call(aT)==r||false}function p(aW){var aT=true;if(!aW){return aT}var aU=al.call(aW),aV=aW.length;if((aU==H||aU==R||(aG.argsClass?aU==j:g(aW)))||(aU==av&&typeof aV=="number"&&aA(aW.splice))){return !aV}Y(aW,function(){return(aT=false)});return aT}function aA(aT){return typeof aT=="function"}if(aA(/x/)){aA=function(aT){return typeof aT=="function"&&al.call(aT)==u}}function E(aT){return !!(aT&&am[typeof aT])}function aQ(aT){return aT===null}function aJ(aT){return typeof aT=="string"||aT&&typeof aT=="object"&&al.call(aT)==R||false}function M(aT){return typeof aT=="undefined"}function ah(aV,aW,aU){var aT={};aW=A.createCallback(aW,aU,3);Y(aV,function(aZ,aY,aX){aT[aY]=aW(aZ,aY,aX)});return aT}function D(aY,aZ,aU){var aT=[];aZ=A.createCallback(aZ,aU,3);if(f(aY)){var aV=-1,aW=aY.length;while(++aV2?F(aU,17,z(arguments,2),null,aT):F(aU,1,null,null,aT)}function o(aY,aU,aZ){var aX=typeof aY;if(aY==null||aX=="function"){return aS(aY,aU,aZ)}if(aX!="object"){return aq(aY)}var aW=J(aY),aV=aW[0],aT=aY[aV];if(aW.length==1&&aT===aT&&!E(aT)){return function(a1){var a0=a1[aV];return aT===a0&&(aT!==0||(1/aT==1/a0)) +}}return function(a1){var a2=aW.length,a0=false;while(a2--){if(!(a0=aB(a1[aW[a2]],aY[aW[a2]],null,true))){break}}return a0}}function T(aT){return aT}function aw(){}function aq(aT){return function(aU){return aU[aT]}}A.assign=aC;A.bind=aE;A.compact=C;A.createCallback=o;A.filter=D;A.forEach=ax;A.forIn=ai;A.forOwn=Y;A.keys=J;A.map=x;A.mapValues=ah;A.property=aq;A.collect=x;A.each=ax;A.extend=aC;A.select=D;A.clone=B;A.find=aR;A.identity=T;A.isArguments=g;A.isArray=f;A.isDate=m;A.isEmpty=p;A.isFunction=aA;A.isNull=aQ;A.isObject=E;A.isString=aJ;A.isUndefined=M;A.noop=aw;A.detect=aR;A.findWhere=aR;A.VERSION="2.4.1";if(v&&N){if(aN){(N.exports=A)._=A}}}.call(this))}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],10:[function(b,c,a){(function(){var g=b("JSON"),i=b("./lib_managed/lodash"),f=b("./lib/detectors").localStorageAccessible,h=b("./lib/helpers"),d=typeof a!=="undefined"?a:this;d.OutQueueManager=function(z,q,t,B,o,m,s,v){var y=true; +var n,j=false,x,l;var r="/com.snowplowanalytics.snowplow/tp2";o=(f()&&B&&o)||1;n=["snowplowOutQueue",z,q,"post2"].join("_");if(B){try{l=g.parse(localStorage.getItem(n))}catch(w){}}if(!i.isArray(l)){l=[]}t.outQueues.push(l);if(o>1){t.bufferFlushers.push(function(){if(!j){A(s,v)}})}function C(F){var D=0;for(var E=0;E=55296&&G<=57343){D+=4;E++}else{if(G<65535){D+=3}else{D+=4}}}}}return D}function u(J,G,E,H){x=G+r;var I=J;var D={evt:I,bytes:C(g.stringify(I))};hasPost=window.XMLHttpRequest&&("withCredentials" in new XMLHttpRequest());if(D.bytes>=m){h.warn("Event of size "+D.bytes+" is too long - the maximum size is "+m);if(hasPost){var K=p(x,E,H);K.send(g.stringify([D.evt]))}else{h.warn("Browser doesn't support secure credentials")}return}else{l.push(D)}var F=false;if(B){F=h.attemptWriteLocalStorage(n,g.stringify(l))}if(!j&&(!F||l.length>=o)){A(E,H)}}function A(E,H){while(l.length&&typeof l[0]!=="string"&&typeof l[0]!=="object"){l.shift() +}if(l.length<1){j=false;return}if(!i.isString(x)){throw"No Snowplow collector configured, cannot track"}j=true;var I=l[0];var J=p(x,E,H);var D=setTimeout(function(){J.abort();j=false},1000);function F(L){var N=0;var M=0;while(N=m){break}else{N+=1}}return N}var K=F(l);J.onreadystatechange=function(){if(J.readyState===4&&J.status>=200&&J.status<400){for(var L=0;L=400){clearTimeout(D);j=false}}};var G=i.map(l.slice(0,K),function(L){return L.evt});if(G.length>0){J.send(g.stringify(G))}}function p(E,D,F){var G=new XMLHttpRequest();G.open("POST",E,true);G.withCredentials=D;G.setRequestHeader("Content-Type","application/json; charset=UTF-8");G.setRequestHeader("x-api-key",F);return G}return{enqueueRequest:u,executeQueue:A}}}())},{"./lib/detectors":7,"./lib/helpers":8,"./lib_managed/lodash":9,JSON:1}],11:[function(b,c,a){(function(){var i=b("./lib_managed/lodash"),h=b("./lib/helpers"),d=b("./in_queue"),g=b("./tracker"),f=typeof a!=="undefined"?a:this; +f.Snowplow=function(m,r){var l=document,n=window,p="js-100.6.3",o={outQueues:[],bufferFlushers:[],expireDateTime:null,hasLoaded:false,registeredOnLoadHandlers:[]};function q(){var t;i.forEach(o.bufferFlushers,function(u){u()});if(o.expireDateTime){do{t=new Date();if(i.filter(o.outQueues,function(u){return u.length>0}).length===0){break}}while(t.getTime()=0.2.0-alpha.3 <0.3.0", - "resolved": "https://registry.npmjs.org/grunt-s3/-/grunt-s3-0.2.0-alpha.3.tgz", - "dependencies": { - "underscore.deferred": { - "version": "0.1.5", - "from": "underscore.deferred@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/underscore.deferred/-/underscore.deferred-0.1.5.tgz" - }, - "knox": { - "version": "0.8.10", - "from": "knox@>=0.8.0 <0.9.0", - "resolved": "https://registry.npmjs.org/knox/-/knox-0.8.10.tgz", + "@types/chai": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-3.4.34.tgz", + "integrity": "sha1-1TNXkoI7sJzd1eOMPSEbcJGDhU0=", + "dev": true + }, + "@types/node": { + "version": "6.0.48", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.48.tgz", + "integrity": "sha1-hszBX2a3PLvF6zSDOYk2xYUSKzw=", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1.js": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", + "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", + "dev": true + }, + "assert": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", + "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", + "dev": true + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "aws-sdk": { + "version": "2.1.50", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1.50.tgz", + "integrity": "sha1-Zd3CuEDmkCEIftNfKC1jKgUpShs=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true + }, + "benchmark": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.1.tgz", + "integrity": "sha1-57X23NAhU67RMtScWWuBWlf2wHE=", + "dev": true, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", + "dev": true + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-5.0.1.tgz", + "integrity": "sha1-QZdxmyDG4KqglFHFER5T77b7wY0=", + "dev": true + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-11.2.0.tgz", + "integrity": "sha1-oRu53SCdeVcrgT9+7q+Cil9cDk4=", + "dev": true, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.0.tgz", + "integrity": "sha512-W2bIMLYoZ9oow7TyePpMJk9l9LY7O3R61a/68bVCDOtnJynnwe3ZeW2IzzSkrQnPKNdJrxVDn3ALZNisSBwb7g==", + "dev": true + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true + }, + "buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-to-vinyl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", + "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-1.0.0.tgz", + "integrity": "sha1-MGN+4mKXisBxdOFtf4LwrQbgha0=", + "dev": true + }, + "builtins": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=", + "dev": true + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true + }, + "charm": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.2.0.tgz", + "integrity": "sha1-us0G2HF3WTYvemYqHpZ691N/2os=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "dev": true + }, + "clean-css": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.8.tgz", + "integrity": "sha1-X8A3oUpoIbuU/BI18DybNyZvmpU=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "closure-compiler": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/closure-compiler/-/closure-compiler-0.2.3.tgz", + "integrity": "sha1-8k+cPwNHVZe3KqVLJirpl4PalTQ=", + "dev": true + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combine-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", + "integrity": "sha1-m0oJwxYDPXaODxHgKfonMOB5rZY=", + "dev": true + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true + }, + "commondir": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", + "integrity": "sha1-ifAP3NUbUZxXhzP+xWPmptp/W+I=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.10.tgz", + "integrity": "sha1-rMO79WAsuMyYDGrIQPp9hgPj7zY=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true + }, + "constants-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true + }, + "crypto-browserify": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", + "dev": true + }, + "csso": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.4.3.tgz", + "integrity": "sha1-XVsM7b1PXgX+95vHnkD++2RL84Y=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decompress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", + "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", + "dev": true, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true + } + } + }, + "decompress-tar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", + "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", + "dev": true, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true + } + } + }, + "decompress-tarbz2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", + "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", + "dev": true, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true + } + } + }, + "decompress-targz": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", + "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", + "dev": true, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true + } + } + }, + "decompress-unzip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", + "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", + "dev": true, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true + } + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "deps-sort": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", + "integrity": "sha1-Kd//U+F7Nq7K51MK27v2IsLtGnE=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true + }, + "detective": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", + "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", + "dev": true + }, + "diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.1.0.tgz", + "integrity": "sha1-eYpJOBqkZBUem08Ob/Kwmooa0j8=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true + }, + "digdug": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/digdug/-/digdug-1.6.5.tgz", + "integrity": "sha512-xvpTA8tDioRRpV75nGVAm9xdSJEmesuRh8s1FVg0bUyn+OK0rZEVqYW0bY57pyxAXhDCB6Lnpf6nlFh8V4qrgg==", + "dev": true, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "dojo": { + "version": "2.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/dojo/-/dojo-2.0.0-alpha.7.tgz", + "integrity": "sha1-wrJdQ9j3LMycj+iaNJBqLSceXJE=", + "dev": true + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.7.1.tgz", + "integrity": "sha1-MOz89mypjcZ80v0WKr626vqM5vw=", + "dev": true, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true + } + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", + "integrity": "sha1-dYSdz+k9EPsFfDAFWv29UdBqjiQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true + }, + "fast-levenshtein": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz", + "integrity": "sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true + }, + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.2.1.tgz", + "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", + "dev": true, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + } + } + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "dev": true, + "optional": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, "dependencies": { - "xml2js": { - "version": "0.2.8", - "from": "xml2js@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", - "dependencies": { - "sax": { - "version": "0.5.8", - "from": "sax@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz" - } - } - }, - "debug": { - "version": "0.7.4", - "from": "debug@>=0.7.0 <0.8.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" - }, - "stream-counter": { - "version": "0.1.0", - "from": "stream-counter@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.1.0.tgz", - "dependencies": { - "readable-stream": { - "version": "1.0.33", - "from": "readable-stream@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", - "dependencies": { - "core-util-is": { - "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" - }, - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - } - } - } - } + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "dev": true, + "optional": true + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "optional": true + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "dependencies": { + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + } + } + }, + "grunt-aws": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/grunt-aws/-/grunt-aws-0.6.2.tgz", + "integrity": "sha1-JncoLBLwxdE1TNXr4g7gWpBcN+w=", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "lodash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.3.1.tgz", + "integrity": "sha1-pGY7U2hriV/wdOK6UE37dqjit3A=", + "dev": true + } + } + }, + "grunt-browserify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/grunt-browserify/-/grunt-browserify-4.0.1.tgz", + "integrity": "sha1-9c7ZAmlYqADy6ImOGk3x5SX/af8=", + "dev": true, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "grunt-contrib-concat": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-0.3.0.tgz", + "integrity": "sha1-SPoNQzbSm2U62CJaa9b4VrRIPjI=", + "dev": true + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "dependencies": { + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + } + } + }, + "grunt-lodash": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/grunt-lodash/-/grunt-lodash-0.3.0.tgz", + "integrity": "sha1-2Rq6E/2cs3HJQ8InY/Pb3ZUgtMc=", + "dev": true, + "dependencies": { + "lodash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.0.0.tgz", + "integrity": "sha1-nc+eP6wErQo4yeLbacn7fOJtq8I=", + "dev": true + } + } + }, + "grunt-yui-compressor": { + "version": "git://github.com/snowplow/grunt-yui-compressor.git#1190dd16757c7f6af7674ce3ae9b3305bb66c2fa", + "dev": true + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true + } + } + }, + "gzip-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", + "dev": true + }, + "handlebars": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "dev": true, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inline-source-map": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.5.0.tgz", + "integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=", + "dev": true + }, + "insert-module-globals": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.6.3.tgz", + "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", + "dev": true + }, + "intern": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/intern/-/intern-3.4.6.tgz", + "integrity": "sha512-Blk3oIUR2X+tdAT8JoGitOjTwud68A1k+IW9Tmbzb4KfRaH4rCQSKhZXwIgrY6eAeL/LUwrLUpKPC66hieGl0g==", + "dev": true, + "dependencies": { + "glob": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", + "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "source-map": { + "version": "0.1.33", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.33.tgz", + "integrity": "sha1-xlkpenOvGMBzsKoufMkeMWtcVww=", + "dev": true + } + } + }, + "is-absolute": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", + "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true + }, + "is-bzip2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", + "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true + }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, + "is-natural-number": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", + "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", + "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-tar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", + "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", + "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "istanbul": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.1.tgz", + "integrity": "sha1-zXMI6zSdBbnyGBYyukxKO1NNJyQ=", + "dev": true, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true } } }, - "mime": { - "version": "1.2.11", - "from": "mime@>=1.2.5 <1.3.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true + }, + "JSON": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/JSON/-/JSON-1.0.0.tgz", + "integrity": "sha1-hoFTHCj4Q4oHVYn/BySCRuqWDYw=", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true + }, + "jszip": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz", + "integrity": "sha1-dET9hVHd8+XacZj+oMkbyDCMwnQ=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + }, + "labeled-stream-splicer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true + }, + "leadfoot": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/leadfoot/-/leadfoot-1.7.4.tgz", + "integrity": "sha1-ojpuzqPRx/yrEk+jwpDwRz8UGtU=", + "dev": true + }, + "levn": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", + "integrity": "sha1-uo0znQykphDjo/FFucr0iAcVUFQ=", + "dev": true + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "lodash-amd": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/lodash-amd/-/lodash-amd-4.16.4.tgz", + "integrity": "sha1-2qBiWlCNwH4jcoIkqiet1qJJlDQ=", + "dev": true + }, + "lodash-cli": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash-cli/-/lodash-cli-2.4.2.tgz", + "integrity": "sha1-kLv1YlF1zfFgvI+V3KZKn40qhAw=", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.7.tgz", + "integrity": "sha1-J185oO7oBWlHkJJPNurDjh222AI=", + "dev": true + }, + "lodash": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "integrity": "sha1-W3cjA03aTSYuWkb7LFjXzCL3FCA=", + "dev": true }, - "temporary": { + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true + }, + "uglify-js": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.6.tgz", + "integrity": "sha1-MXZqTYIrq/XzLBQJYlHtklkpitM=", + "dev": true + } + } + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "maxmin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true + } + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mimetype": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mimetype/-/mimetype-0.0.8.tgz", + "integrity": "sha1-+zACJ5S793Jct7Rt+CDofdkf0IY=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "dependencies": { + "minimist": { "version": "0.0.8", - "from": "temporary@0.0.8", - "resolved": "https://registry.npmjs.org/temporary/-/temporary-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "module-deps": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.9.1.tgz", + "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "dev": true, + "optional": true + }, + "node-minify": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/node-minify/-/node-minify-1.3.9.tgz", + "integrity": "sha1-ziGLtPi1ORWq6xLavs++zwxUlr0=", + "dev": true, + "dependencies": { + "glob": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.1.tgz", + "integrity": "sha1-FqiblKw2GypnCgoUGiGtUbQ40h0=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "node-uuid": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=", + "dev": true + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", + "integrity": "sha1-t1qJlaLUF98ltuTjhi9QqohlE2g=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "outpipe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", + "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", + "dev": true, + "dependencies": { + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true + } + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true + }, + "platform": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.1.tgz", + "integrity": "sha1-SSIQiSM1vTExwKCN2i2T7DVD5CM=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true + }, + "read-only-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-1.1.1.tgz", + "integrity": "sha1-Xad8eZ7ROI0++IoYRxu1kk+KC6E=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true + } + } + }, + "readable-wrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", + "integrity": "sha1-O1ohHGMeEjA6VJkcgGwX564ga/8=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "sax": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.3.tgz", + "integrity": "sha1-N3NxSg2RV8qqcwKXHvpcbc2lUtY=", + "dev": true + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true + }, + "semver": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-2.2.1.tgz", + "integrity": "sha1-eUEYKz/8xYC/8cF5QqzfeVHA0hM=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true + }, + "sha1": { + "version": "git://github.com/pvorb/node-sha1.git#910081c83f3661507d9d89e66e3f38d8b59d5559", + "dev": true + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true + }, + "shell-quote": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sqwish": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/sqwish/-/sqwish-0.2.2.tgz", + "integrity": "sha1-AP4maBBPEii1u37nOe9gEhu8sFc=", + "dev": true + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true + }, + "stream-combiner2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", + "integrity": "sha1-unKmtQy/q/qVD8i8h2BL0B62BnE=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "stream-http": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-1.7.1.tgz", + "integrity": "sha1-09Km4Uw2o4udr7GZrue7xXBRmXg=", + "dev": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "stream-splicer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.2.tgz", + "integrity": "sha1-PARBvhW5v04iYnXm3IOWR0VUZmE=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true + }, + "strip-dirs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", + "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true + }, + "sum-up": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", + "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", + "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "dev": true + }, + "tar-stream": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", + "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true + } + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true + } + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.1.tgz", + "integrity": "sha1-7bvhiIujUl3tOnv4NrMLNAXTFhs=", + "dev": true, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "dependencies": { + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true + } + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true + }, + "vinyl-assign": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", + "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", + "dev": true + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true + }, + "watchify": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/watchify/-/watchify-3.9.0.tgz", + "integrity": "sha1-8HX9LoqGrN6Eztum5cKgvt1SPZ4=", + "dev": true, + "dependencies": { + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "browser-pack": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", + "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", + "dev": true + }, + "browserify": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.4.0.tgz", + "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", + "dev": true + }, + "buffer": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", + "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, "dependencies": { - "package": { - "version": "1.0.1", - "from": "package@>=1.0.0 <1.2.0", - "resolved": "https://registry.npmjs.org/package/-/package-1.0.1.tgz" + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true } } } } + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml2js": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", + "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", + "dev": true + }, + "xmlbuilder": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.2.tgz", + "integrity": "sha1-F3bWXz/brUcKCNhgTN6xxOVA/4M=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", + "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", + "dev": true } } }