e 1 년 전
부모
커밋
aaca8d0690
50개의 변경된 파일3593개의 추가작업 그리고 6개의 파일을 삭제
  1. 26 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/.eslintrc.js
  2. 51 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/CHANGES.md
  3. 10 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/LICENSE.md
  4. 270 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/README.md
  5. BIN
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/branding/logo.png
  6. BIN
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/branding/logo.sketch
  7. 48 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/package.json
  8. 359 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/src/pubsub.js
  9. 7 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/.eslintrc.js
  10. 55 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/helper.js
  11. 50 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-bug-9.js
  12. 24 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-clearSubscriptions.js
  13. 32 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-countSubscriptions.js
  14. 20 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-getSubscriptions.js
  15. 204 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-hierarchical-addressing.js
  16. 43 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-issue-54.js
  17. 211 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-publish.js
  18. 92 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribe.js
  19. 28 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribeAll.js
  20. 32 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribeOnce.js
  21. 21 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-symbol.js
  22. 159 0
      node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-unsubscribe.js
  23. 26 0
      node_modules/pubsub-js/.eslintrc.js
  24. 51 0
      node_modules/pubsub-js/CHANGES.md
  25. 10 0
      node_modules/pubsub-js/LICENSE.md
  26. 270 0
      node_modules/pubsub-js/README.md
  27. BIN
      node_modules/pubsub-js/branding/logo.png
  28. BIN
      node_modules/pubsub-js/branding/logo.sketch
  29. 48 0
      node_modules/pubsub-js/package.json
  30. 359 0
      node_modules/pubsub-js/src/pubsub.js
  31. 7 0
      node_modules/pubsub-js/test/.eslintrc.js
  32. 55 0
      node_modules/pubsub-js/test/helper.js
  33. 50 0
      node_modules/pubsub-js/test/test-bug-9.js
  34. 24 0
      node_modules/pubsub-js/test/test-clearSubscriptions.js
  35. 32 0
      node_modules/pubsub-js/test/test-countSubscriptions.js
  36. 20 0
      node_modules/pubsub-js/test/test-getSubscriptions.js
  37. 204 0
      node_modules/pubsub-js/test/test-hierarchical-addressing.js
  38. 43 0
      node_modules/pubsub-js/test/test-issue-54.js
  39. 211 0
      node_modules/pubsub-js/test/test-publish.js
  40. 92 0
      node_modules/pubsub-js/test/test-subscribe.js
  41. 28 0
      node_modules/pubsub-js/test/test-subscribeAll.js
  42. 32 0
      node_modules/pubsub-js/test/test-subscribeOnce.js
  43. 21 0
      node_modules/pubsub-js/test/test-symbol.js
  44. 159 0
      node_modules/pubsub-js/test/test-unsubscribe.js
  45. 5 0
      package.json
  46. 30 2
      vue2.0/vue高阶/2.归纳.md
  47. 7 1
      vue2.0/vue高阶/hello_vue/src/App.vue
  48. 31 3
      vue2.0/vue高阶/hello_vue/src/components/Demo5.vue
  49. 33 0
      vue2.0/vue高阶/hello_vue/src/components/Demo6.vue
  50. 3 0
      vue2.0/vue高阶/hello_vue/src/main.js

+ 26 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/.eslintrc.js

@@ -0,0 +1,26 @@
+module.exports = {
+    "env": {
+        "browser": true,
+        "commonjs": true,
+        "node": true
+    },
+    "extends": "eslint:recommended",
+    "rules": {
+        "indent": [
+            "error",
+            4
+        ],
+        "linebreak-style": [
+            "error",
+            "unix"
+        ],
+        "quotes": [
+            "error",
+            "single"
+        ],
+        "semi": [
+            "error",
+            "always"
+        ]
+    }
+};

+ 51 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/CHANGES.md

@@ -0,0 +1,51 @@
+# Changes
+
+## 1.9.4
+
+- [`ae3284d`](https://github.com/mroderick/PubSubJS/commit/ae3284d46054b189e143b405e1bfc6c09643bf77)
+  Use existing root.pubSub when present (#213) (abishek-srinivasan)
+    >
+    > This means that loading `pubsub-js` more than once in the same environment will work as the author expects. A warning will be output on the console to make the developer aware of the duplication.
+
+_Released on 2021-11-11._
+
+## 1.9.3
+
+- [`a810919`](https://github.com/mroderick/PubSubJS/commit/a81091962dd4836da9da6dcf7aafeca4aeb9f815)
+  Fix countSubscriptions
+    >
+    > This was introduced in ad93491c760ebc0429a7e9072b2747b2c2ce0a0a, but had
+    > a bug that was not covered by unit tests.
+    >
+
+_Released on 2021-02-18._
+
+## 1.9.2
+
+- [`83648dd`](https://github.com/mroderick/PubSubJS/commit/83648dd9e48762a8058904debe1b653850bbcf5c)
+  fix #115 don't directly use hasOwnProperty (jianghaoran)
+
+_Released on 2020-12-14._
+
+## 1.9.1
+
+- [`ead7906`](https://github.com/mroderick/PubSubJS/commit/ead79069b79df8c4f7d3324047cdb3b9d4c33571)
+  Fix amd module export (#173) (Sven Busse)
+    >
+    > Co-authored-by: Kevin <58685946+Kepeters@users.noreply.github.com>
+
+_Released on 2020-11-13._
+
+## 1.9.0
+
+- [`3fb21e3`](https://github.com/mroderick/PubSubJS/commit/3fb21e309f8bb9fd32906b25b3a607bc32e8b1a7)
+  Add `subscribeAll` method (Subin Varghese)
+
+_Released on 2020-08-17._
+
+## 1.8.0
+
+* Add `getSubscriptions`
+* Add countSubscriptions
+
+_Released on 2019-12-20._

+ 10 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/LICENSE.md

@@ -0,0 +1,10 @@
+The MIT License (MIT)
+=====================
+
+Copyright © `2010` [Morgan Roderick](https://roderick.dk), [http://roderick.dk/](https://roderick.dk) <[morgan@roderick.dk](mailto:morgan@roderick.dk)>
+
+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.

+ 270 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/README.md

@@ -0,0 +1,270 @@
+<div align="center">
+  <p>
+    <img src="https://raw.githubusercontent.com/mroderick/PubSubJS/master/branding/logo.png"/ alt="PubSubJS" title="PubSubJS" width="200" height="200">
+  </p>
+
+  <p>
+    <a href="https://travis-ci.org/mroderick/PubSubJS"><img src="https://img.shields.io/travis/mroderick/PubSubJS.svg?style=flat-square" alt="Travis build status" title="Travis build status" /></a><!--
+    --><a href="https://david-dm.org/mroderick/PubSubJS"><img src="https://img.shields.io/david/mroderick/pubsubjs.svg?style=flat-square" alt="Dependencies" title="Powered by David" /></a><!--
+    --><a href="https://david-dm.org/mroderick/PubSubJS#info=devDependencies&view=table"><img src="https://img.shields.io/david/dev/mroderick/pubsubjs.svg?style=flat-square" alt="DevDependencies" title="Powered by David" /></a><!--
+    --><a href="https://www.npmjs.com/package/pubsub-js"><img src="https://img.shields.io/npm/v/pubsub-js.svg?style=flat-square" alt="NPM version" title="Click to go to NPM" /></a><!--
+    --><a href="https://github.com/mroderick/PubSubJS/blob/master/LICENSE.md"><img src="https://img.shields.io/npm/l/pubsub-js.svg?style=flat-square" alt="MIT License" title="License" /></a><!--
+    --><a href="https://www.npmjs.com/package/pubsub-js"><img src="https://img.shields.io/npm/dm/pubsub-js.svg?style=flat-square" alt="NPM downloads/month" title="Click to go to NPM" /></a><!--
+    --><a href="https://coveralls.io/github/mroderick/PubSubJS"><img src="https://img.shields.io/coveralls/github/mroderick/PubSubJS.svg?style=flat-square" alt="Coverage Status" title="View Coverage"/></a>
+  </p>
+</div>
+
+PubSubJS is a [topic-based](http://en.wikipedia.org/wiki/Publish–subscribe_pattern#Message_filtering) [publish/subscribe](http://en.wikipedia.org/wiki/Publish/subscribe) library written in JavaScript.
+
+PubSubJS has synchronisation decoupling, so topics are published asynchronously. This helps keep your program predictable as the originator of topics will not be blocked while consumers process them.
+
+For the adventurous, PubSubJS also supports synchronous topic publication. This can give a speedup in some environments (browsers, not all), but can also lead to some very difficult to reason about programs, where one topic triggers publication of another topic in the same execution chain.
+
+#### Single process
+
+PubSubJS is designed to be used within a **single process**, and is not a good candidate for multi-process applications (like [Node.js – Cluster](http://nodejs.org/api/cluster.html) with many sub-processes). If your Node.js app is a single process app, you're good. If it is (or is going to be) a multi-process app, you're probably better off using [redis Pub/Sub](http://redis.io/topics/pubsub) or similar
+
+## Key features
+
+* Dependency free
+* synchronisation decoupling
+* ES3 compatible. PubSubJS should be able to run everywhere that can execute JavaScript. Browsers, servers, ebook readers, old phones, game consoles.
+* AMD / CommonJS module support
+* No modification of subscribers (jQuery custom events modify subscribers)
+* Easy to understand and use (thanks to synchronisation decoupling)
+* Small(ish), less than 1kb minified and gzipped
+
+## Getting PubSubJS
+
+There are several ways of getting PubSubJS
+
+* Install via npm (`npm install pubsub-js`)
+* Use it directly from a CDN
+    - http://www.jsdelivr.com/#!pubsubjs
+    - https://cdnjs.com/libraries/pubsub-js
+    - https://unpkg.com/pubsub-js
+* [Download a tagged version](https://github.com/mroderick/PubSubJS/tags) from GitHub
+
+**Note: the last version of this library available via bower is v1.5.4**
+
+## Examples
+
+First you have to import the module:
+
+```javascript
+import PubSub from 'pubsub-js'
+
+// or when using CommonJS
+const PubSub = require('pubsub-js');
+```
+
+### Basic example
+
+```javascript
+// create a function to subscribe to topics
+var mySubscriber = function (msg, data) {
+    console.log( msg, data );
+};
+
+// add the function to the list of subscribers for a particular topic
+// we're keeping the returned token, in order to be able to unsubscribe
+// from the topic later on
+var token = PubSub.subscribe('MY TOPIC', mySubscriber);
+
+// publish a topic asynchronously
+PubSub.publish('MY TOPIC', 'hello world!');
+
+// publish a topic synchronously, which is faster in some environments,
+// but will get confusing when one topic triggers new topics in the
+// same execution chain
+// USE WITH CAUTION, HERE BE DRAGONS!!!
+PubSub.publishSync('MY TOPIC', 'hello world!');
+```
+
+### Cancel specific subscription
+
+```javascript
+// create a function to receive the topic
+var mySubscriber = function (msg, data) {
+    console.log(msg, data);
+};
+
+// add the function to the list of subscribers to a particular topic
+// we're keeping the returned token, in order to be able to unsubscribe
+// from the topic later on
+var token = PubSub.subscribe('MY TOPIC', mySubscriber);
+
+// unsubscribe this subscriber from this topic
+PubSub.unsubscribe(token);
+```
+
+### Cancel all subscriptions for a function
+
+```javascript
+// create a function to receive the topic
+var mySubscriber = function(msg, data) {
+    console.log(msg, data);
+};
+
+// unsubscribe mySubscriber from ALL topics
+PubSub.unsubscribe(mySubscriber);
+```
+
+### Clear all subscriptions for a topic
+
+```javascript
+PubSub.subscribe('a', myFunc1);
+PubSub.subscribe('a.b', myFunc2);
+PubSub.subscribe('a.b.c', myFunc3);
+
+PubSub.unsubscribe('a.b');
+// no further notifications for 'a.b' and 'a.b.c' topics
+// notifications for 'a' will still get published
+```
+
+### Clear all subscriptions
+
+```javascript
+PubSub.clearAllSubscriptions();
+// all subscriptions are removed
+```
+
+### Get Subscriptions
+
+```javascript
+PubSub.getSubscriptions('token');
+// subscriptions by token from all topics
+```
+
+### Count Subscriptions
+
+```javascript
+PubSub.countSubscriptions('token');
+// count by token from all topics
+```
+
+
+### Error Handling
+```javascript
+// isPublished is a boolean that represents if any subscribers was registered for this topic
+var isPublished = PubSub.publish('a');
+
+// token will be false if something went wrong and subscriber was not registered
+var token = PubSub.subscribe('MY TOPIC', mySubscriber); 
+```
+
+### Hierarchical addressing
+
+```javascript
+// create a subscriber to receive all topics from a hierarchy of topics
+var myToplevelSubscriber = function (msg, data) {
+    console.log('top level: ', msg, data);
+}
+
+// subscribe to all topics in the 'car' hierarchy
+PubSub.subscribe('car', myToplevelSubscriber);
+
+// create a subscriber to receive only leaf topic from hierarchy op topics
+var mySpecificSubscriber = function (msg, data) {
+    console.log('specific: ', msg, data);
+}
+
+// subscribe only to 'car.drive' topics
+PubSub.subscribe('car.drive', mySpecificSubscriber);
+
+// Publish some topics
+PubSub.publish('car.purchase', {name: 'my new car'});
+PubSub.publish('car.drive', {speed: '14'});
+PubSub.publish('car.sell', {newOwner: 'someone else'});
+
+// In this scenario, myToplevelSubscriber will be called for all
+// topics, three times in total
+// But, mySpecificSubscriber will only be called once, as it only
+// subscribes to the 'car.drive' topic
+```
+
+
+
+
+## Tips
+
+Use "constants" for topics and not string literals. PubSubJS uses strings as topics, and will happily try to deliver your topics with ANY topic. So, save yourself from frustrating debugging by letting the JavaScript engine complain
+when you make typos.
+
+### Example of use of "constants"
+
+```javascript
+// 👎 Bad usage
+PubSub.subscribe('hello', function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish('hello', 'world');
+
+// 👍 Better usage
+var MY_TOPIC = 'hello';
+PubSub.subscribe(MY_TOPIC, function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish(MY_TOPIC, 'world');
+```
+
+### Example of use of "symbol constants" with ES6/7 syntax
+
+```javascript
+// event-types.js
+export const MY_TOPIC = Symbol('MY_TOPIC')
+
+// somefile.js
+import { MY_TOPIC } from './event-types.js'
+PubSub.subscribe(MY_TOPIC, function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish(MY_TOPIC, 'world');
+```
+
+### Immediate Exceptions for stack traces in developer tools
+
+As of version 1.3.2, you can force immediate exceptions (instead of delayed exceptions), which has the benefit of maintaining the stack trace when viewed in dev tools.
+
+This should be considered a development only option, as PubSubJS was designed to try to deliver your topics to all subscribers, even when some fail.
+
+Setting immediate exceptions in development is easy, just tell PubSubJS about it after it has been loaded.
+
+```javascript
+PubSub.immediateExceptions = true;
+```
+
+## Contributing to PubSubJS
+
+Please see [CONTRIBUTING.md](CONTRIBUTING.md)
+
+
+## More about Publish/Subscribe
+
+* [The Many Faces of Publish/Subscribe](http://www.cs.ru.nl/~pieter/oss/manyfaces.pdf) (PDF)
+* [Addy Osmani's mini book on Patterns](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript)
+* [Publish / Subscribe Systems, A summary of 'The Many Faces of Publish / Subscribe'](http://downloads.ohohlfeld.com/talks/hohlfeld_schroeder-publish_subscribe_systems-dsmware_eurecom2007.pdf)
+
+## Versioning
+
+PubSubJS uses [Semantic Versioning](http://semver.org/) for predictable versioning.
+
+## Changelog
+
+Please see [https://github.com/mroderick/PubSubJS/releases](https://github.com/mroderick/PubSubJS/releases)
+
+## License
+
+MIT: http://mrgnrdrck.mit-license.org
+
+## Alternatives
+
+These are a few alternative projects that also implement topic based publish subscribe in JavaScript.
+
+* http://www.joezimjs.com/projects/publish-subscribe-jquery-plugin/
+* http://amplifyjs.com/api/pubsub/
+* http://radio.uxder.com/ — oriented towards 'channels', free of dependencies
+* https://github.com/pmelander/Subtopic - supports vanilla, underscore, jQuery and is even available in NuGet

BIN
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/branding/logo.png


BIN
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/branding/logo.sketch


+ 48 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/package.json

@@ -0,0 +1,48 @@
+{
+  "name": "pubsub-js",
+  "version": "1.9.4",
+  "description": "Dependency free publish/subscribe library",
+  "main": "./src/pubsub.js",
+  "directories": {
+    "lib": "src",
+    "test": "test"
+  },
+  "scripts": {
+    "coverage": "nyc --reporter=lcov --reporter=text --reporter=json-summary npm test",
+    "prepublishOnly": "jsdoc2md --template ./docs/template.hbs --files ./src/*.js > ./docs/docs.md",
+    "lint": "eslint src/ test/",
+    "test": "mocha",
+    "preversion": "npm test",
+    "version": "changes --commits --footer",
+    "postversion": "git push --follow-tags && npm publish --access public"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mroderick/PubSubJS.git"
+  },
+  "keywords": [
+    "pub/sub",
+    "pubsub",
+    "publish/subscribe",
+    "publish",
+    "subscribe"
+  ],
+  "author": {
+    "name": "Morgan Roderick",
+    "email": "morgan@roderick.dk",
+    "url": "http://roderick.dk"
+  },
+  "license": "MIT",
+  "devDependencies": {
+    "@studio/changes": "^2.0.0",
+    "eslint": "4.19.1",
+    "jsdoc-to-markdown": "^5.0.3",
+    "mocha": "7.1.0",
+    "nyc": "15.0.0",
+    "referee": "^1.2.0",
+    "sinon": "9.0.0"
+  },
+  "__npminstall_done": true,
+  "_from": "pubsub-js@1.9.4",
+  "_resolved": "https://registry.npmmirror.com/pubsub-js/-/pubsub-js-1.9.4.tgz"
+}

+ 359 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/src/pubsub.js

@@ -0,0 +1,359 @@
+/**
+ * Copyright (c) 2010,2011,2012,2013,2014 Morgan Roderick http://roderick.dk
+ * License: MIT - http://mrgnrdrck.mit-license.org
+ *
+ * https://github.com/mroderick/PubSubJS
+ */
+
+(function (root, factory){
+    'use strict';
+
+    var PubSub = {};
+
+    if (root.PubSub) {
+        PubSub = root.PubSub;
+        console.warn("PubSub already loaded, using existing version");
+    } else {
+        root.PubSub = PubSub;
+        factory(PubSub);
+    }
+    // CommonJS and Node.js module support
+    if (typeof exports === 'object'){
+        if (module !== undefined && module.exports) {
+            exports = module.exports = PubSub; // Node.js specific `module.exports`
+        }
+        exports.PubSub = PubSub; // CommonJS module 1.1.1 spec
+        module.exports = exports = PubSub; // CommonJS
+    }
+    // AMD support
+    /* eslint-disable no-undef */
+    else if (typeof define === 'function' && define.amd){
+        define(function() { return PubSub; });
+        /* eslint-enable no-undef */
+    }
+
+}(( typeof window === 'object' && window ) || this, function (PubSub){
+    'use strict';
+
+    var messages = {},
+        lastUid = -1,
+        ALL_SUBSCRIBING_MSG = '*';
+
+    function hasKeys(obj){
+        var key;
+
+        for (key in obj){
+            if ( Object.prototype.hasOwnProperty.call(obj, key) ){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns a function that throws the passed exception, for use as argument for setTimeout
+     * @alias throwException
+     * @function
+     * @param { Object } ex An Error object
+     */
+    function throwException( ex ){
+        return function reThrowException(){
+            throw ex;
+        };
+    }
+
+    function callSubscriberWithDelayedExceptions( subscriber, message, data ){
+        try {
+            subscriber( message, data );
+        } catch( ex ){
+            setTimeout( throwException( ex ), 0);
+        }
+    }
+
+    function callSubscriberWithImmediateExceptions( subscriber, message, data ){
+        subscriber( message, data );
+    }
+
+    function deliverMessage( originalMessage, matchedMessage, data, immediateExceptions ){
+        var subscribers = messages[matchedMessage],
+            callSubscriber = immediateExceptions ? callSubscriberWithImmediateExceptions : callSubscriberWithDelayedExceptions,
+            s;
+
+        if ( !Object.prototype.hasOwnProperty.call( messages, matchedMessage ) ) {
+            return;
+        }
+
+        for (s in subscribers){
+            if ( Object.prototype.hasOwnProperty.call(subscribers, s)){
+                callSubscriber( subscribers[s], originalMessage, data );
+            }
+        }
+    }
+
+    function createDeliveryFunction( message, data, immediateExceptions ){
+        return function deliverNamespaced(){
+            var topic = String( message ),
+                position = topic.lastIndexOf( '.' );
+
+            // deliver the message as it is now
+            deliverMessage(message, message, data, immediateExceptions);
+
+            // trim the hierarchy and deliver message to each level
+            while( position !== -1 ){
+                topic = topic.substr( 0, position );
+                position = topic.lastIndexOf('.');
+                deliverMessage( message, topic, data, immediateExceptions );
+            }
+
+            deliverMessage(message, ALL_SUBSCRIBING_MSG, data, immediateExceptions);
+        };
+    }
+
+    function hasDirectSubscribersFor( message ) {
+        var topic = String( message ),
+            found = Boolean(Object.prototype.hasOwnProperty.call( messages, topic ) && hasKeys(messages[topic]));
+
+        return found;
+    }
+
+    function messageHasSubscribers( message ){
+        var topic = String( message ),
+            found = hasDirectSubscribersFor(topic) || hasDirectSubscribersFor(ALL_SUBSCRIBING_MSG),
+            position = topic.lastIndexOf( '.' );
+
+        while ( !found && position !== -1 ){
+            topic = topic.substr( 0, position );
+            position = topic.lastIndexOf( '.' );
+            found = hasDirectSubscribersFor(topic);
+        }
+
+        return found;
+    }
+
+    function publish( message, data, sync, immediateExceptions ){
+        message = (typeof message === 'symbol') ? message.toString() : message;
+
+        var deliver = createDeliveryFunction( message, data, immediateExceptions ),
+            hasSubscribers = messageHasSubscribers( message );
+
+        if ( !hasSubscribers ){
+            return false;
+        }
+
+        if ( sync === true ){
+            deliver();
+        } else {
+            setTimeout( deliver, 0 );
+        }
+        return true;
+    }
+
+    /**
+     * Publishes the message, passing the data to it's subscribers
+     * @function
+     * @alias publish
+     * @param { String } message The message to publish
+     * @param {} data The data to pass to subscribers
+     * @return { Boolean }
+     */
+    PubSub.publish = function( message, data ){
+        return publish( message, data, false, PubSub.immediateExceptions );
+    };
+
+    /**
+     * Publishes the message synchronously, passing the data to it's subscribers
+     * @function
+     * @alias publishSync
+     * @param { String } message The message to publish
+     * @param {} data The data to pass to subscribers
+     * @return { Boolean }
+     */
+    PubSub.publishSync = function( message, data ){
+        return publish( message, data, true, PubSub.immediateExceptions );
+    };
+
+    /**
+     * Subscribes the passed function to the passed message. Every returned token is unique and should be stored if you need to unsubscribe
+     * @function
+     * @alias subscribe
+     * @param { String } message The message to subscribe to
+     * @param { Function } func The function to call when a new message is published
+     * @return { String }
+     */
+    PubSub.subscribe = function( message, func ){
+        if ( typeof func !== 'function'){
+            return false;
+        }
+
+        message = (typeof message === 'symbol') ? message.toString() : message;
+
+        // message is not registered yet
+        if ( !Object.prototype.hasOwnProperty.call( messages, message ) ){
+            messages[message] = {};
+        }
+
+        // forcing token as String, to allow for future expansions without breaking usage
+        // and allow for easy use as key names for the 'messages' object
+        var token = 'uid_' + String(++lastUid);
+        messages[message][token] = func;
+
+        // return token for unsubscribing
+        return token;
+    };
+
+    PubSub.subscribeAll = function( func ){
+        return PubSub.subscribe(ALL_SUBSCRIBING_MSG, func);
+    };
+
+    /**
+     * Subscribes the passed function to the passed message once
+     * @function
+     * @alias subscribeOnce
+     * @param { String } message The message to subscribe to
+     * @param { Function } func The function to call when a new message is published
+     * @return { PubSub }
+     */
+    PubSub.subscribeOnce = function( message, func ){
+        var token = PubSub.subscribe( message, function(){
+            // before func apply, unsubscribe message
+            PubSub.unsubscribe( token );
+            func.apply( this, arguments );
+        });
+        return PubSub;
+    };
+
+    /**
+     * Clears all subscriptions
+     * @function
+     * @public
+     * @alias clearAllSubscriptions
+     */
+    PubSub.clearAllSubscriptions = function clearAllSubscriptions(){
+        messages = {};
+    };
+
+    /**
+     * Clear subscriptions by the topic
+     * @function
+     * @public
+     * @alias clearAllSubscriptions
+     * @return { int }
+     */
+    PubSub.clearSubscriptions = function clearSubscriptions(topic){
+        var m;
+        for (m in messages){
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0){
+                delete messages[m];
+            }
+        }
+    };
+
+    /**
+       Count subscriptions by the topic
+     * @function
+     * @public
+     * @alias countSubscriptions
+     * @return { Array }
+    */
+    PubSub.countSubscriptions = function countSubscriptions(topic){
+        var m;
+        // eslint-disable-next-line no-unused-vars
+        var token;
+        var count = 0;
+        for (m in messages) {
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0) {
+                for (token in messages[m]) {
+                    count++;
+                }
+                break;
+            }
+        }
+        return count;
+    };
+
+
+    /**
+       Gets subscriptions by the topic
+     * @function
+     * @public
+     * @alias getSubscriptions
+    */
+    PubSub.getSubscriptions = function getSubscriptions(topic){
+        var m;
+        var list = [];
+        for (m in messages){
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0){
+                list.push(m);
+            }
+        }
+        return list;
+    };
+
+    /**
+     * Removes subscriptions
+     *
+     * - When passed a token, removes a specific subscription.
+     *
+	 * - When passed a function, removes all subscriptions for that function
+     *
+	 * - When passed a topic, removes all subscriptions for that topic (hierarchy)
+     * @function
+     * @public
+     * @alias subscribeOnce
+     * @param { String | Function } value A token, function or topic to unsubscribe from
+     * @example // Unsubscribing with a token
+     * var token = PubSub.subscribe('mytopic', myFunc);
+     * PubSub.unsubscribe(token);
+     * @example // Unsubscribing with a function
+     * PubSub.unsubscribe(myFunc);
+     * @example // Unsubscribing from a topic
+     * PubSub.unsubscribe('mytopic');
+     */
+    PubSub.unsubscribe = function(value){
+        var descendantTopicExists = function(topic) {
+                var m;
+                for ( m in messages ){
+                    if ( Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0 ){
+                        // a descendant of the topic exists:
+                        return true;
+                    }
+                }
+
+                return false;
+            },
+            isTopic    = typeof value === 'string' && ( Object.prototype.hasOwnProperty.call(messages, value) || descendantTopicExists(value) ),
+            isToken    = !isTopic && typeof value === 'string',
+            isFunction = typeof value === 'function',
+            result = false,
+            m, message, t;
+
+        if (isTopic){
+            PubSub.clearSubscriptions(value);
+            return;
+        }
+
+        for ( m in messages ){
+            if ( Object.prototype.hasOwnProperty.call( messages, m ) ){
+                message = messages[m];
+
+                if ( isToken && message[value] ){
+                    delete message[value];
+                    result = value;
+                    // tokens are unique, so we can just stop here
+                    break;
+                }
+
+                if (isFunction) {
+                    for ( t in message ){
+                        if (Object.prototype.hasOwnProperty.call(message, t) && message[t] === value){
+                            delete message[t];
+                            result = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    };
+}));

+ 7 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/.eslintrc.js

@@ -0,0 +1,7 @@
+module.exports = {
+	"env": {
+		"commonjs": true,
+		"mocha": true,
+		"node": true
+	}
+};

+ 55 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/helper.js

@@ -0,0 +1,55 @@
+(function(root, factory){
+    'use strict';
+
+    var define = root.define;
+
+    // CommonJS
+    if (typeof exports === 'object'){
+        module.exports = factory();
+
+        // AMD
+    } else if (typeof define === 'function' && define.amd){
+        define(factory);
+        // Browser
+    } else {
+        root.TestHelper = factory();
+    }
+}( ( typeof window === 'object' && window ) || this, function(){
+
+    'use strict';
+
+    var TestHelper = {},
+        assert = require('referee').assert;
+
+    // helps us make sure that the order of the tests have no impact on their succes
+    function getUniqueString(){
+        if ( getUniqueString.uid === undefined ){
+            getUniqueString.uid = 0;
+        }
+        getUniqueString.uid++;
+
+        return 'my unique String number ' + getUniqueString.uid.toString();
+    }
+
+    // makes sure that all tokens in the passed array are different
+    function assertAllTokensDifferent( tokens ){
+        var length = tokens.length,
+            j, k;
+        assert( tokens.length > 0 );
+        // compare all tokens
+        for ( j = 0; j < length; j++ ){
+            for ( k = j + 1; k < length; k++ ){
+                assert( tokens[j] !== tokens[k] );
+            }
+        }
+
+        // make sure we actually tested something
+        assert.equals( j, length );
+        assert.equals( k, length );
+    }
+
+    TestHelper.getUniqueString = getUniqueString;
+    TestHelper.assertAllTokensDifferent = assertAllTokensDifferent;
+
+    return TestHelper;
+}));

+ 50 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-bug-9.js

@@ -0,0 +1,50 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+/**
+ *	This is a test proving that bug 9 has been fixed.
+ *	See https://github.com/mroderick/PubSubJS/issues/9
+ */
+describe( 'Bug 9, publish method', function() {
+    it('should notify all subscribers in a hierarchy', function( done ){
+        var subscriber1 = sinon.spy(),
+            subscriber2 = sinon.spy(),
+            subscriber3 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( 'a.b.c', subscriber1 );
+        PubSub.subscribe( 'a.b', subscriber2 );
+        PubSub.subscribe( 'a', subscriber3 );
+
+        PubSub.publish( 'a.b.c.d' );
+
+        clock.tick(1);
+
+        assert( subscriber1.calledOnce );
+        assert( subscriber2.calledOnce );
+        assert( subscriber3.calledOnce );
+
+        done();
+        clock.restore();
+    });
+
+    it('should notify individual subscribers, even when there are no subscribers further up', function( done ){
+
+        var rootTopic = 'a.b.c',
+            subscriber = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe(rootTopic, subscriber);
+        PubSub.publish(rootTopic + '.d');
+
+        clock.tick(1);
+
+        assert( subscriber.calledOnce );
+
+        done();
+        clock.restore();
+    });
+});

+ 24 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-clearSubscriptions.js

@@ -0,0 +1,24 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe('clearAllSubscriptions method', function () {
+    it('must clear all subscriptions', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        PubSub.clearAllSubscriptions();
+
+        PubSub.publishSync(topic, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        refute(spy2.called);
+    });
+});

+ 32 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-countSubscriptions.js

@@ -0,0 +1,32 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe('test-countSubscriptions method', function () {
+    it('must be count eq 0', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+
+        var counts = PubSub.countSubscriptions(topic);
+
+        assert.equals(counts,1);
+    });
+
+    it('should count all subscriptions', function() {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        var counts = PubSub.countSubscriptions(topic);
+
+        assert.equals(counts, 2);
+    });
+});

+ 20 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-getSubscriptions.js

@@ -0,0 +1,20 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe('getSubscriptions method', function () {
+    it('must be length eq 0', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+
+        var subscriptions = PubSub.getSubscriptions(topic).length;
+
+        assert.equals(subscriptions,1);
+    });
+
+});

+ 204 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-hierarchical-addressing.js

@@ -0,0 +1,204 @@
+'use strict';
+
+var PubSub = global.PubSub || require('../src/pubsub'),
+    TestHelper = global.TestHelper || require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe( 'Hierarchical addressing', function () {
+    beforeEach(function(){
+        this.clock = sinon.useFakeTimers();
+    });
+
+    afterEach(function(){
+        this.clock.restore();
+    });
+
+    it('publish method should not call any children in a namespace', function( done ) {
+        var messages = ['library', 'library.music'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy );
+        PubSub.publish( messages[0], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 1 );
+
+        done();
+    });
+
+    it('publish method should call a parent namespace', function( done ) {
+        // Publishing library.music should trigger parent library
+        var messages = ['library', 'library.music'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.publish( messages[1], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('publish method should call only a parent namespace', function( done ) {
+        //Publishing library.music should only trigger parents descendants
+        //Even if it has a child
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy );
+        PubSub.publish( messages[1], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('publish method should call all parent namespaces', function( done ) {
+        //Publishing library.music.jazz should trigger all parents
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 3 );
+
+        done();
+    });
+
+    it('publish method should call only parent descendants', function( done ) {
+        //Publishing library.music.jazz should trigger only all parents descendants
+        //Skipping library.playlist and library.playlist.*
+        var messages = [
+                'library',
+                'library.music',
+                'library.music.jazz',
+                'library.playlist',
+                'library.playlist.mine'
+            ],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.subscribe( messages[3], spy );
+        PubSub.subscribe( messages[4], spy );
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 3 );
+
+        done();
+    });
+
+    it('publish method should call all parent descendants deeply', function( done ) {
+        //Publishing library.music.jazz.soft.swing should trigger all but
+        //library.music.playlist.jazz
+        var messages = [
+                'library',
+                'library.music',
+                'library.music.jazz',
+                'library.music.jazz.soft',
+                'library.music.jazz.soft.swing',
+                'library.music.playlist.jazz'
+            ],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.subscribe( messages[3], spy ); //This should be called
+        PubSub.subscribe( messages[4], spy ); //This should be called
+        PubSub.subscribe( messages[5], spy ); //This should be called
+        PubSub.subscribe( messages[6], spy );
+        PubSub.publish( messages[4], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 5 );
+
+        done();
+    });
+
+    it('publish method should still call all parents, even when middle child is unsubscribed', function( done ) {
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString(),
+            token;
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+
+        token = PubSub.subscribe( messages[1], spy );
+
+        PubSub.unsubscribe( token ); //Take out middle child
+
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('unsubscribe method should return tokens when succesfully removing namespaced message', function(){
+        var func = function(){ return undefined; },
+            messages = ['playlist.music', 'playlist.music.jazz'],
+            token1 = PubSub.subscribe( messages[0], func),
+            token2 = PubSub.subscribe( messages[1], func ),
+            result1 = PubSub.unsubscribe( token1 ),
+            result2 = PubSub.unsubscribe( token2 );
+
+        assert.equals( result1, token1 );
+        assert.equals( result2, token2 );
+    });
+
+    it('unsubscribe method should unsubscribe parent without affecting orphans', function( done ){
+        var data = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            messages = ['playlist', 'playlist.music', 'playlist.music.jazz'],
+            token;
+
+        token = PubSub.subscribe( messages[0], spy ); //Gets unsubscribed
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+
+        PubSub.unsubscribe( token );
+
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+});

+ 43 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-issue-54.js

@@ -0,0 +1,43 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+/**
+ *	This is a test proving that bug 54 has been fixed.
+ *	See https://github.com/mroderick/PubSubJS/issues/54
+ */
+describe( 'Issue 54, publish method', function () {
+
+    it('should notify all subscribers, even when one is unsubscribed', function( done ){
+        var topic = TestHelper.getUniqueString(),
+            token1,
+            token1Unsubscribed = false,
+            subscriber1 = function(){
+                PubSub.unsubscribe(token1);
+                token1Unsubscribed = true;
+            },
+            spy1 = sinon.spy(subscriber1),
+            spy2 = sinon.spy(),
+            spy3 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        token1 = PubSub.subscribe( topic, spy1 );
+        PubSub.subscribe( topic, spy2 );
+        PubSub.subscribe( topic, spy3 );
+
+        PubSub.publish( topic );
+
+        clock.tick(1);
+
+        assert( token1Unsubscribed === true );
+        assert( spy1.calledOnce );
+        assert( spy2.calledOnce );
+        assert( spy3.calledOnce );
+
+        done();
+        clock.restore();
+    });
+});

+ 211 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-publish.js

@@ -0,0 +1,211 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe( 'publish method', function () {
+    it('should return false if there are no subscribers', function(){
+        var message = TestHelper.getUniqueString();
+        assert.equals( PubSub.publish( message ), false );
+    });
+
+    it('should return true if there are subscribers to a message', function(){
+        var message = TestHelper.getUniqueString(),
+            func = function(){ return undefined; };
+
+        PubSub.subscribe( message, func );
+        assert( PubSub.publish( message ) );
+    });
+
+    it('should return false, when there are no longer any subscribers to a message', function(){
+        var message = TestHelper.getUniqueString(),
+            func = function(){ return undefined; },
+            token = PubSub.subscribe(message, func);
+
+        PubSub.unsubscribe(token);
+        assert.equals( PubSub.publish(message), false );
+    });
+
+    it('should call all subscribers for a message exactly once', function(){
+        var message = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe( message, spy1 );
+        PubSub.subscribe( message, spy2 );
+
+        PubSub.publishSync( message, 'my payload' ); // force sync here, easier to test
+
+        assert( spy1.calledOnce );
+        assert( spy2.calledOnce );
+    });
+
+    it('should call all ONLY subscribers of the published message', function(){
+        var message1 = TestHelper.getUniqueString(),
+            message2 = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe( message1, spy1 );
+        PubSub.subscribe( message2, spy2 );
+
+        PubSub.publishSync( message1, 'some payload' );
+
+        // ensure the first subscriber IS called
+        assert(	 spy1.called );
+        // ensure the second subscriber IS NOT called
+        assert.equals( spy2.callCount, 0 );
+    });
+
+    it('should call subscribers with message as first argument', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, 'some payload' );
+
+        assert( spy.calledWith( message ) );
+    });
+
+    it('should call subscribers with data as second argument', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, data );
+
+        assert( spy.calledWith( message, data ) );
+    });
+
+    it('should publish method asyncronously', function( done ){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publish( message, data );
+
+        assert.equals( spy.callCount, 0 );
+        clock.tick(1);
+        assert.equals( spy.callCount, 1 );
+
+        done();
+        clock.restore();
+    });
+
+    it('publishSync method should allow syncronous publication', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, data );
+
+        assert.equals( spy.callCount, 1 );
+    });
+
+    it('should call all subscribers, even if there are exceptions', function( done ){
+        var message = TestHelper.getUniqueString(),
+            func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( message, func1 );
+        PubSub.subscribe( message, spy1 );
+        PubSub.subscribe( message, spy2 );
+
+        assert.exception( function(){
+            PubSub.publishSync( message, 'some data' );
+            clock.tick(1);
+        });
+
+        assert( spy1.called );
+        assert( spy2.called );
+
+        done();
+        clock.restore();
+    });
+
+    it('should fail immediately on exceptions when immediateExceptions is true', function(){
+        var message = TestHelper.getUniqueString(),
+            func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+
+        PubSub.subscribe( message, func1 );
+        PubSub.subscribe( message, spy1 );
+
+        PubSub.immediateExceptions = true;
+
+        assert.exception( function(){
+            PubSub.publishSync( message, 'some data' );
+        });
+
+        refute( spy1.called );
+        refute( spy2.called );
+
+        // make sure we restore PubSub to it's original state
+        delete PubSub.immediateExceptions;
+    });
+
+    it('should fail immediately on exceptions in namespaces when immediateExceptions is true',  function(){
+        var func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy();
+
+        PubSub.subscribe( 'buy', func1 );
+        PubSub.subscribe( 'buy', spy1 );
+
+        PubSub.immediateExceptions = true;
+
+        assert.exception( function(){
+            PubSub.publishSync( 'buy.tomatoes', 'some data' );
+        });
+
+        refute( spy1.called );
+
+        // make sure we restore PubSub to it's original state
+        delete PubSub.immediateExceptions;
+    });
+
+    it('should call all subscribers, even when there are unsubscriptions within', function(done){
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            func1 = function func1(){
+                PubSub.unsubscribe(func1);
+                spy1();
+            },
+
+            spy2 = sinon.spy(),
+            func2 = function func2(){
+                PubSub.unsubscribe(func2);
+                spy2();
+            },
+
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe(topic, func1);
+        PubSub.subscribe(topic, func2);
+
+        PubSub.publish(topic, 'some data');
+        clock.tick(1);
+
+        assert(spy1.called, 'expected spy1 to be called');
+        assert(spy2.called, 'expected spy2 to be called');
+
+        clock.restore();
+        done();
+    });
+});

+ 92 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribe.js

@@ -0,0 +1,92 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute;
+
+describe( 'subscribe method', function() {
+    it('should return token as String', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message , func );
+
+        assert.isString( token );
+    });
+
+    it('should return new token for several subscriptions with same function', function(){
+        var func = function(){ return undefined; },
+            tokens = [],
+            iterations = 10,
+            message = TestHelper.getUniqueString(),
+            i;
+
+        // build an array of tokens
+        for ( i = 0; i < iterations; i++ ){
+            tokens.push( PubSub.subscribe( message, func ) );
+        }
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return unique tokens for each namespaced subscription', function(){
+        var func = function(){ return undefined; },
+            tokens = [],
+            messages = ['library', 'library.music', 'library.music.jazz'],
+            i;
+
+        // build an array of tokens
+        for ( i = 0; i < messages.length; i++ ){
+            tokens.push( PubSub.subscribe( messages[i], func ) );
+        }
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return unique token for unique functions', function(){
+        var tokens = [],
+            iterations = 10,
+            message = TestHelper.getUniqueString(),
+            i;
+
+        function bakeFunc( value ){
+            return function(){
+                return value;
+            };
+        }
+
+        // build an array of tokens, passing in a different function for each subscription
+        for ( i = 0; i < iterations; i++ ){
+            tokens.push( PubSub.subscribe( message, bakeFunc( i ) ) );
+        }
+
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return false when subscriber argument is not a function', function(){
+        var invalidSubscribers = [undefined, null, 'a string', 123, [], {}, new Date()],
+            topic = TestHelper.getUniqueString(),
+            i;
+
+        for ( i = 0; i < invalidSubscribers.length; i++ ){
+            assert.equals(PubSub.subscribe(topic, invalidSubscribers[i]), false);
+        }
+
+        assert.equals(i, invalidSubscribers.length);
+    });
+
+    it('must not throw errors when publishing with invalid subscribers', function(){
+        var invalidSubscribers = [undefined, null, 'a string', 123, [], {}, new Date()],
+            topic = TestHelper.getUniqueString(),
+            i;
+
+        for (i = 0; i < invalidSubscribers.length; i++){
+            PubSub.subscribe(topic, invalidSubscribers[i]);
+        }
+
+        refute.exception(function(){
+            PubSub.publish(topic, TestHelper.getUniqueString());
+        });
+    });
+});

+ 28 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribeAll.js

@@ -0,0 +1,28 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+
+describe( 'subscribeAll method', function() {
+
+    it('should return token as String', function(){
+        var func = function(){ return undefined; },
+            token = PubSub.subscribeAll( func );
+
+        assert.isString( token );
+    });
+
+    it('should subscribe for all messages', function() {
+        var message = TestHelper.getUniqueString(),
+            subscribeFn = sinon.spy();
+
+        PubSub.subscribeAll( subscribeFn );
+        PubSub.publishSync( message, 'some payload' );
+
+        assert( subscribeFn.calledOnce );
+    });
+
+} );

+ 32 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-subscribeOnce.js

@@ -0,0 +1,32 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+
+describe( 'subscribeOnce method', function() {
+
+    it( 'should return PubSub', function() {
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            pubSub = PubSub.subscribeOnce( message , func );
+        assert.same( pubSub, PubSub );
+    } );
+
+    it( 'must be executed only once', function() {
+
+        var topic = TestHelper.getUniqueString(),
+            spy = sinon.spy();
+        
+        PubSub.subscribeOnce( topic, spy );
+        for ( var i = 0; i < 3; i++ ) {
+            PubSub.publishSync( topic, TestHelper.getUniqueString() );
+        }
+
+        assert( spy.calledOnce );
+
+    } );
+
+} );

+ 21 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-symbol.js

@@ -0,0 +1,21 @@
+/* global Symbol */
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    assert = require('referee').assert;
+
+describe( 'subscribe and publish', function() {
+    before(function(){
+        if (typeof Symbol !== 'function'){
+            this.skip();
+        }
+    });
+    it('should work on Symbol() type message/topic', function(){
+        var MESSAGE = Symbol('MESSAGE');
+        var func = function(){ return undefined; };
+
+        PubSub.subscribe( MESSAGE, func );
+        
+        assert( PubSub.publish( MESSAGE ), true );
+    });
+});

+ 159 - 0
node_modules/.store/pubsub-js@1.9.4/node_modules/pubsub-js/test/test-unsubscribe.js

@@ -0,0 +1,159 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe( 'unsubscribe method', function() {
+    it('should return token when succesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message, func),
+            result = PubSub.unsubscribe( token );
+
+        assert.equals( result, token );
+    });
+
+    it('should return false when unsuccesful', function(){
+        var unknownToken = 'my unknown token',
+            result = PubSub.unsubscribe( unknownToken ),
+            func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message, func );
+
+        // first, let's try a completely unknown token
+        assert.equals( result, false );
+
+        // now let's try unsubscribing the same method twice
+        PubSub.unsubscribe( token );
+        assert.equals( PubSub.unsubscribe( token ), false );
+    });
+
+    it('with function argument should return true when succesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            result;
+
+        PubSub.subscribe( message, func);
+        result = PubSub.unsubscribe( func );
+
+        assert.equals( result, true );
+    });
+
+    it('with function argument should return false when unsuccesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            unknownToken = 'my unknown token',
+            result = PubSub.unsubscribe( unknownToken );
+
+        // first, let's try a completely unknown token
+
+        assert.equals( result, false );
+
+        // now let's try unsubscribing the same method twice
+        PubSub.subscribe( message, func );
+        PubSub.subscribe( message, func );
+        PubSub.subscribe( message, func );
+
+        // unsubscribe once, this should remove all subscriptions for message
+        PubSub.unsubscribe( func );
+
+        // unsubscribe again
+        assert.equals( PubSub.unsubscribe( func ), false );
+    });
+
+    it('with topic argument, must clear all exactly matched subscriptions', function(){
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        PubSub.unsubscribe(topic);
+
+        PubSub.publishSync(topic, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        refute(spy2.called);
+    });
+
+    it('with topic argument, must only clear matched subscriptions', function(){
+        var topic1 = TestHelper.getUniqueString(),
+            topic2 = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic1, spy1);
+        PubSub.subscribe(topic2, spy2);
+
+        PubSub.unsubscribe(topic1);
+
+        PubSub.publishSync(topic1, TestHelper.getUniqueString());
+        PubSub.publishSync(topic2, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        assert(spy2.called);
+    });
+
+    it('with topic argument, must clear all matched hierarchical subscriptions', function(){
+        var topic = TestHelper.getUniqueString(),
+            topicA = topic + '.a',
+            topicB = topic + '.a.b',
+            topicC = topic + '.a.b.c',
+            spyA = sinon.spy(),
+            spyB = sinon.spy(),
+            spyC = sinon.spy();
+
+        PubSub.subscribe(topicA, spyA);
+        PubSub.subscribe(topicB, spyB);
+        PubSub.subscribe(topicC, spyC);
+
+        PubSub.unsubscribe(topicB);
+
+        PubSub.publishSync(topicC, TestHelper.getUniqueString());
+
+        assert(spyA.called);
+        refute(spyB.called);
+        refute(spyC.called);
+    });
+
+    it('with parent topic argument, must clear all child subscriptions', function() {
+        var topic = TestHelper.getUniqueString(),
+            topicA = topic + '.a',
+            topicB = topic + '.a.b',
+            topicC = topic + '.a.b.c',
+            spyB = sinon.spy(),
+            spyC = sinon.spy();
+
+        // subscribe only to  children:
+        PubSub.subscribe(topicB, spyB);
+        PubSub.subscribe(topicC, spyC);
+
+        // but unsubscribe from a parent:
+        PubSub.unsubscribe(topicA);
+
+        PubSub.publishSync(topicB, TestHelper.getUniqueString());
+        PubSub.publishSync(topicC, TestHelper.getUniqueString());
+
+        refute(spyB.called);
+        refute(spyC.called);
+    });
+
+    it('must not throw exception when unsubscribing as part of publishing', function(){
+        refute.exception(function(){
+            var topic = TestHelper.getUniqueString(),
+                sub1 = function(){
+                    PubSub.unsubscribe(sub1);
+                },
+                sub2 = function(){ return undefined; };
+
+            PubSub.subscribe( topic, sub1 );
+            PubSub.subscribe( topic, sub2 );
+
+            PubSub.publishSync( topic, 'hello world!' );
+        });
+    });
+});

+ 26 - 0
node_modules/pubsub-js/.eslintrc.js

@@ -0,0 +1,26 @@
+module.exports = {
+    "env": {
+        "browser": true,
+        "commonjs": true,
+        "node": true
+    },
+    "extends": "eslint:recommended",
+    "rules": {
+        "indent": [
+            "error",
+            4
+        ],
+        "linebreak-style": [
+            "error",
+            "unix"
+        ],
+        "quotes": [
+            "error",
+            "single"
+        ],
+        "semi": [
+            "error",
+            "always"
+        ]
+    }
+};

+ 51 - 0
node_modules/pubsub-js/CHANGES.md

@@ -0,0 +1,51 @@
+# Changes
+
+## 1.9.4
+
+- [`ae3284d`](https://github.com/mroderick/PubSubJS/commit/ae3284d46054b189e143b405e1bfc6c09643bf77)
+  Use existing root.pubSub when present (#213) (abishek-srinivasan)
+    >
+    > This means that loading `pubsub-js` more than once in the same environment will work as the author expects. A warning will be output on the console to make the developer aware of the duplication.
+
+_Released on 2021-11-11._
+
+## 1.9.3
+
+- [`a810919`](https://github.com/mroderick/PubSubJS/commit/a81091962dd4836da9da6dcf7aafeca4aeb9f815)
+  Fix countSubscriptions
+    >
+    > This was introduced in ad93491c760ebc0429a7e9072b2747b2c2ce0a0a, but had
+    > a bug that was not covered by unit tests.
+    >
+
+_Released on 2021-02-18._
+
+## 1.9.2
+
+- [`83648dd`](https://github.com/mroderick/PubSubJS/commit/83648dd9e48762a8058904debe1b653850bbcf5c)
+  fix #115 don't directly use hasOwnProperty (jianghaoran)
+
+_Released on 2020-12-14._
+
+## 1.9.1
+
+- [`ead7906`](https://github.com/mroderick/PubSubJS/commit/ead79069b79df8c4f7d3324047cdb3b9d4c33571)
+  Fix amd module export (#173) (Sven Busse)
+    >
+    > Co-authored-by: Kevin <58685946+Kepeters@users.noreply.github.com>
+
+_Released on 2020-11-13._
+
+## 1.9.0
+
+- [`3fb21e3`](https://github.com/mroderick/PubSubJS/commit/3fb21e309f8bb9fd32906b25b3a607bc32e8b1a7)
+  Add `subscribeAll` method (Subin Varghese)
+
+_Released on 2020-08-17._
+
+## 1.8.0
+
+* Add `getSubscriptions`
+* Add countSubscriptions
+
+_Released on 2019-12-20._

+ 10 - 0
node_modules/pubsub-js/LICENSE.md

@@ -0,0 +1,10 @@
+The MIT License (MIT)
+=====================
+
+Copyright © `2010` [Morgan Roderick](https://roderick.dk), [http://roderick.dk/](https://roderick.dk) <[morgan@roderick.dk](mailto:morgan@roderick.dk)>
+
+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.

+ 270 - 0
node_modules/pubsub-js/README.md

@@ -0,0 +1,270 @@
+<div align="center">
+  <p>
+    <img src="https://raw.githubusercontent.com/mroderick/PubSubJS/master/branding/logo.png"/ alt="PubSubJS" title="PubSubJS" width="200" height="200">
+  </p>
+
+  <p>
+    <a href="https://travis-ci.org/mroderick/PubSubJS"><img src="https://img.shields.io/travis/mroderick/PubSubJS.svg?style=flat-square" alt="Travis build status" title="Travis build status" /></a><!--
+    --><a href="https://david-dm.org/mroderick/PubSubJS"><img src="https://img.shields.io/david/mroderick/pubsubjs.svg?style=flat-square" alt="Dependencies" title="Powered by David" /></a><!--
+    --><a href="https://david-dm.org/mroderick/PubSubJS#info=devDependencies&view=table"><img src="https://img.shields.io/david/dev/mroderick/pubsubjs.svg?style=flat-square" alt="DevDependencies" title="Powered by David" /></a><!--
+    --><a href="https://www.npmjs.com/package/pubsub-js"><img src="https://img.shields.io/npm/v/pubsub-js.svg?style=flat-square" alt="NPM version" title="Click to go to NPM" /></a><!--
+    --><a href="https://github.com/mroderick/PubSubJS/blob/master/LICENSE.md"><img src="https://img.shields.io/npm/l/pubsub-js.svg?style=flat-square" alt="MIT License" title="License" /></a><!--
+    --><a href="https://www.npmjs.com/package/pubsub-js"><img src="https://img.shields.io/npm/dm/pubsub-js.svg?style=flat-square" alt="NPM downloads/month" title="Click to go to NPM" /></a><!--
+    --><a href="https://coveralls.io/github/mroderick/PubSubJS"><img src="https://img.shields.io/coveralls/github/mroderick/PubSubJS.svg?style=flat-square" alt="Coverage Status" title="View Coverage"/></a>
+  </p>
+</div>
+
+PubSubJS is a [topic-based](http://en.wikipedia.org/wiki/Publish–subscribe_pattern#Message_filtering) [publish/subscribe](http://en.wikipedia.org/wiki/Publish/subscribe) library written in JavaScript.
+
+PubSubJS has synchronisation decoupling, so topics are published asynchronously. This helps keep your program predictable as the originator of topics will not be blocked while consumers process them.
+
+For the adventurous, PubSubJS also supports synchronous topic publication. This can give a speedup in some environments (browsers, not all), but can also lead to some very difficult to reason about programs, where one topic triggers publication of another topic in the same execution chain.
+
+#### Single process
+
+PubSubJS is designed to be used within a **single process**, and is not a good candidate for multi-process applications (like [Node.js – Cluster](http://nodejs.org/api/cluster.html) with many sub-processes). If your Node.js app is a single process app, you're good. If it is (or is going to be) a multi-process app, you're probably better off using [redis Pub/Sub](http://redis.io/topics/pubsub) or similar
+
+## Key features
+
+* Dependency free
+* synchronisation decoupling
+* ES3 compatible. PubSubJS should be able to run everywhere that can execute JavaScript. Browsers, servers, ebook readers, old phones, game consoles.
+* AMD / CommonJS module support
+* No modification of subscribers (jQuery custom events modify subscribers)
+* Easy to understand and use (thanks to synchronisation decoupling)
+* Small(ish), less than 1kb minified and gzipped
+
+## Getting PubSubJS
+
+There are several ways of getting PubSubJS
+
+* Install via npm (`npm install pubsub-js`)
+* Use it directly from a CDN
+    - http://www.jsdelivr.com/#!pubsubjs
+    - https://cdnjs.com/libraries/pubsub-js
+    - https://unpkg.com/pubsub-js
+* [Download a tagged version](https://github.com/mroderick/PubSubJS/tags) from GitHub
+
+**Note: the last version of this library available via bower is v1.5.4**
+
+## Examples
+
+First you have to import the module:
+
+```javascript
+import PubSub from 'pubsub-js'
+
+// or when using CommonJS
+const PubSub = require('pubsub-js');
+```
+
+### Basic example
+
+```javascript
+// create a function to subscribe to topics
+var mySubscriber = function (msg, data) {
+    console.log( msg, data );
+};
+
+// add the function to the list of subscribers for a particular topic
+// we're keeping the returned token, in order to be able to unsubscribe
+// from the topic later on
+var token = PubSub.subscribe('MY TOPIC', mySubscriber);
+
+// publish a topic asynchronously
+PubSub.publish('MY TOPIC', 'hello world!');
+
+// publish a topic synchronously, which is faster in some environments,
+// but will get confusing when one topic triggers new topics in the
+// same execution chain
+// USE WITH CAUTION, HERE BE DRAGONS!!!
+PubSub.publishSync('MY TOPIC', 'hello world!');
+```
+
+### Cancel specific subscription
+
+```javascript
+// create a function to receive the topic
+var mySubscriber = function (msg, data) {
+    console.log(msg, data);
+};
+
+// add the function to the list of subscribers to a particular topic
+// we're keeping the returned token, in order to be able to unsubscribe
+// from the topic later on
+var token = PubSub.subscribe('MY TOPIC', mySubscriber);
+
+// unsubscribe this subscriber from this topic
+PubSub.unsubscribe(token);
+```
+
+### Cancel all subscriptions for a function
+
+```javascript
+// create a function to receive the topic
+var mySubscriber = function(msg, data) {
+    console.log(msg, data);
+};
+
+// unsubscribe mySubscriber from ALL topics
+PubSub.unsubscribe(mySubscriber);
+```
+
+### Clear all subscriptions for a topic
+
+```javascript
+PubSub.subscribe('a', myFunc1);
+PubSub.subscribe('a.b', myFunc2);
+PubSub.subscribe('a.b.c', myFunc3);
+
+PubSub.unsubscribe('a.b');
+// no further notifications for 'a.b' and 'a.b.c' topics
+// notifications for 'a' will still get published
+```
+
+### Clear all subscriptions
+
+```javascript
+PubSub.clearAllSubscriptions();
+// all subscriptions are removed
+```
+
+### Get Subscriptions
+
+```javascript
+PubSub.getSubscriptions('token');
+// subscriptions by token from all topics
+```
+
+### Count Subscriptions
+
+```javascript
+PubSub.countSubscriptions('token');
+// count by token from all topics
+```
+
+
+### Error Handling
+```javascript
+// isPublished is a boolean that represents if any subscribers was registered for this topic
+var isPublished = PubSub.publish('a');
+
+// token will be false if something went wrong and subscriber was not registered
+var token = PubSub.subscribe('MY TOPIC', mySubscriber); 
+```
+
+### Hierarchical addressing
+
+```javascript
+// create a subscriber to receive all topics from a hierarchy of topics
+var myToplevelSubscriber = function (msg, data) {
+    console.log('top level: ', msg, data);
+}
+
+// subscribe to all topics in the 'car' hierarchy
+PubSub.subscribe('car', myToplevelSubscriber);
+
+// create a subscriber to receive only leaf topic from hierarchy op topics
+var mySpecificSubscriber = function (msg, data) {
+    console.log('specific: ', msg, data);
+}
+
+// subscribe only to 'car.drive' topics
+PubSub.subscribe('car.drive', mySpecificSubscriber);
+
+// Publish some topics
+PubSub.publish('car.purchase', {name: 'my new car'});
+PubSub.publish('car.drive', {speed: '14'});
+PubSub.publish('car.sell', {newOwner: 'someone else'});
+
+// In this scenario, myToplevelSubscriber will be called for all
+// topics, three times in total
+// But, mySpecificSubscriber will only be called once, as it only
+// subscribes to the 'car.drive' topic
+```
+
+
+
+
+## Tips
+
+Use "constants" for topics and not string literals. PubSubJS uses strings as topics, and will happily try to deliver your topics with ANY topic. So, save yourself from frustrating debugging by letting the JavaScript engine complain
+when you make typos.
+
+### Example of use of "constants"
+
+```javascript
+// 👎 Bad usage
+PubSub.subscribe('hello', function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish('hello', 'world');
+
+// 👍 Better usage
+var MY_TOPIC = 'hello';
+PubSub.subscribe(MY_TOPIC, function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish(MY_TOPIC, 'world');
+```
+
+### Example of use of "symbol constants" with ES6/7 syntax
+
+```javascript
+// event-types.js
+export const MY_TOPIC = Symbol('MY_TOPIC')
+
+// somefile.js
+import { MY_TOPIC } from './event-types.js'
+PubSub.subscribe(MY_TOPIC, function (msg, data) {
+	console.log(data)
+});
+
+PubSub.publish(MY_TOPIC, 'world');
+```
+
+### Immediate Exceptions for stack traces in developer tools
+
+As of version 1.3.2, you can force immediate exceptions (instead of delayed exceptions), which has the benefit of maintaining the stack trace when viewed in dev tools.
+
+This should be considered a development only option, as PubSubJS was designed to try to deliver your topics to all subscribers, even when some fail.
+
+Setting immediate exceptions in development is easy, just tell PubSubJS about it after it has been loaded.
+
+```javascript
+PubSub.immediateExceptions = true;
+```
+
+## Contributing to PubSubJS
+
+Please see [CONTRIBUTING.md](CONTRIBUTING.md)
+
+
+## More about Publish/Subscribe
+
+* [The Many Faces of Publish/Subscribe](http://www.cs.ru.nl/~pieter/oss/manyfaces.pdf) (PDF)
+* [Addy Osmani's mini book on Patterns](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript)
+* [Publish / Subscribe Systems, A summary of 'The Many Faces of Publish / Subscribe'](http://downloads.ohohlfeld.com/talks/hohlfeld_schroeder-publish_subscribe_systems-dsmware_eurecom2007.pdf)
+
+## Versioning
+
+PubSubJS uses [Semantic Versioning](http://semver.org/) for predictable versioning.
+
+## Changelog
+
+Please see [https://github.com/mroderick/PubSubJS/releases](https://github.com/mroderick/PubSubJS/releases)
+
+## License
+
+MIT: http://mrgnrdrck.mit-license.org
+
+## Alternatives
+
+These are a few alternative projects that also implement topic based publish subscribe in JavaScript.
+
+* http://www.joezimjs.com/projects/publish-subscribe-jquery-plugin/
+* http://amplifyjs.com/api/pubsub/
+* http://radio.uxder.com/ — oriented towards 'channels', free of dependencies
+* https://github.com/pmelander/Subtopic - supports vanilla, underscore, jQuery and is even available in NuGet

BIN
node_modules/pubsub-js/branding/logo.png


BIN
node_modules/pubsub-js/branding/logo.sketch


+ 48 - 0
node_modules/pubsub-js/package.json

@@ -0,0 +1,48 @@
+{
+  "name": "pubsub-js",
+  "version": "1.9.4",
+  "description": "Dependency free publish/subscribe library",
+  "main": "./src/pubsub.js",
+  "directories": {
+    "lib": "src",
+    "test": "test"
+  },
+  "scripts": {
+    "coverage": "nyc --reporter=lcov --reporter=text --reporter=json-summary npm test",
+    "prepublishOnly": "jsdoc2md --template ./docs/template.hbs --files ./src/*.js > ./docs/docs.md",
+    "lint": "eslint src/ test/",
+    "test": "mocha",
+    "preversion": "npm test",
+    "version": "changes --commits --footer",
+    "postversion": "git push --follow-tags && npm publish --access public"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mroderick/PubSubJS.git"
+  },
+  "keywords": [
+    "pub/sub",
+    "pubsub",
+    "publish/subscribe",
+    "publish",
+    "subscribe"
+  ],
+  "author": {
+    "name": "Morgan Roderick",
+    "email": "morgan@roderick.dk",
+    "url": "http://roderick.dk"
+  },
+  "license": "MIT",
+  "devDependencies": {
+    "@studio/changes": "^2.0.0",
+    "eslint": "4.19.1",
+    "jsdoc-to-markdown": "^5.0.3",
+    "mocha": "7.1.0",
+    "nyc": "15.0.0",
+    "referee": "^1.2.0",
+    "sinon": "9.0.0"
+  },
+  "__npminstall_done": true,
+  "_from": "pubsub-js@1.9.4",
+  "_resolved": "https://registry.npmmirror.com/pubsub-js/-/pubsub-js-1.9.4.tgz"
+}

+ 359 - 0
node_modules/pubsub-js/src/pubsub.js

@@ -0,0 +1,359 @@
+/**
+ * Copyright (c) 2010,2011,2012,2013,2014 Morgan Roderick http://roderick.dk
+ * License: MIT - http://mrgnrdrck.mit-license.org
+ *
+ * https://github.com/mroderick/PubSubJS
+ */
+
+(function (root, factory){
+    'use strict';
+
+    var PubSub = {};
+
+    if (root.PubSub) {
+        PubSub = root.PubSub;
+        console.warn("PubSub already loaded, using existing version");
+    } else {
+        root.PubSub = PubSub;
+        factory(PubSub);
+    }
+    // CommonJS and Node.js module support
+    if (typeof exports === 'object'){
+        if (module !== undefined && module.exports) {
+            exports = module.exports = PubSub; // Node.js specific `module.exports`
+        }
+        exports.PubSub = PubSub; // CommonJS module 1.1.1 spec
+        module.exports = exports = PubSub; // CommonJS
+    }
+    // AMD support
+    /* eslint-disable no-undef */
+    else if (typeof define === 'function' && define.amd){
+        define(function() { return PubSub; });
+        /* eslint-enable no-undef */
+    }
+
+}(( typeof window === 'object' && window ) || this, function (PubSub){
+    'use strict';
+
+    var messages = {},
+        lastUid = -1,
+        ALL_SUBSCRIBING_MSG = '*';
+
+    function hasKeys(obj){
+        var key;
+
+        for (key in obj){
+            if ( Object.prototype.hasOwnProperty.call(obj, key) ){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns a function that throws the passed exception, for use as argument for setTimeout
+     * @alias throwException
+     * @function
+     * @param { Object } ex An Error object
+     */
+    function throwException( ex ){
+        return function reThrowException(){
+            throw ex;
+        };
+    }
+
+    function callSubscriberWithDelayedExceptions( subscriber, message, data ){
+        try {
+            subscriber( message, data );
+        } catch( ex ){
+            setTimeout( throwException( ex ), 0);
+        }
+    }
+
+    function callSubscriberWithImmediateExceptions( subscriber, message, data ){
+        subscriber( message, data );
+    }
+
+    function deliverMessage( originalMessage, matchedMessage, data, immediateExceptions ){
+        var subscribers = messages[matchedMessage],
+            callSubscriber = immediateExceptions ? callSubscriberWithImmediateExceptions : callSubscriberWithDelayedExceptions,
+            s;
+
+        if ( !Object.prototype.hasOwnProperty.call( messages, matchedMessage ) ) {
+            return;
+        }
+
+        for (s in subscribers){
+            if ( Object.prototype.hasOwnProperty.call(subscribers, s)){
+                callSubscriber( subscribers[s], originalMessage, data );
+            }
+        }
+    }
+
+    function createDeliveryFunction( message, data, immediateExceptions ){
+        return function deliverNamespaced(){
+            var topic = String( message ),
+                position = topic.lastIndexOf( '.' );
+
+            // deliver the message as it is now
+            deliverMessage(message, message, data, immediateExceptions);
+
+            // trim the hierarchy and deliver message to each level
+            while( position !== -1 ){
+                topic = topic.substr( 0, position );
+                position = topic.lastIndexOf('.');
+                deliverMessage( message, topic, data, immediateExceptions );
+            }
+
+            deliverMessage(message, ALL_SUBSCRIBING_MSG, data, immediateExceptions);
+        };
+    }
+
+    function hasDirectSubscribersFor( message ) {
+        var topic = String( message ),
+            found = Boolean(Object.prototype.hasOwnProperty.call( messages, topic ) && hasKeys(messages[topic]));
+
+        return found;
+    }
+
+    function messageHasSubscribers( message ){
+        var topic = String( message ),
+            found = hasDirectSubscribersFor(topic) || hasDirectSubscribersFor(ALL_SUBSCRIBING_MSG),
+            position = topic.lastIndexOf( '.' );
+
+        while ( !found && position !== -1 ){
+            topic = topic.substr( 0, position );
+            position = topic.lastIndexOf( '.' );
+            found = hasDirectSubscribersFor(topic);
+        }
+
+        return found;
+    }
+
+    function publish( message, data, sync, immediateExceptions ){
+        message = (typeof message === 'symbol') ? message.toString() : message;
+
+        var deliver = createDeliveryFunction( message, data, immediateExceptions ),
+            hasSubscribers = messageHasSubscribers( message );
+
+        if ( !hasSubscribers ){
+            return false;
+        }
+
+        if ( sync === true ){
+            deliver();
+        } else {
+            setTimeout( deliver, 0 );
+        }
+        return true;
+    }
+
+    /**
+     * Publishes the message, passing the data to it's subscribers
+     * @function
+     * @alias publish
+     * @param { String } message The message to publish
+     * @param {} data The data to pass to subscribers
+     * @return { Boolean }
+     */
+    PubSub.publish = function( message, data ){
+        return publish( message, data, false, PubSub.immediateExceptions );
+    };
+
+    /**
+     * Publishes the message synchronously, passing the data to it's subscribers
+     * @function
+     * @alias publishSync
+     * @param { String } message The message to publish
+     * @param {} data The data to pass to subscribers
+     * @return { Boolean }
+     */
+    PubSub.publishSync = function( message, data ){
+        return publish( message, data, true, PubSub.immediateExceptions );
+    };
+
+    /**
+     * Subscribes the passed function to the passed message. Every returned token is unique and should be stored if you need to unsubscribe
+     * @function
+     * @alias subscribe
+     * @param { String } message The message to subscribe to
+     * @param { Function } func The function to call when a new message is published
+     * @return { String }
+     */
+    PubSub.subscribe = function( message, func ){
+        if ( typeof func !== 'function'){
+            return false;
+        }
+
+        message = (typeof message === 'symbol') ? message.toString() : message;
+
+        // message is not registered yet
+        if ( !Object.prototype.hasOwnProperty.call( messages, message ) ){
+            messages[message] = {};
+        }
+
+        // forcing token as String, to allow for future expansions without breaking usage
+        // and allow for easy use as key names for the 'messages' object
+        var token = 'uid_' + String(++lastUid);
+        messages[message][token] = func;
+
+        // return token for unsubscribing
+        return token;
+    };
+
+    PubSub.subscribeAll = function( func ){
+        return PubSub.subscribe(ALL_SUBSCRIBING_MSG, func);
+    };
+
+    /**
+     * Subscribes the passed function to the passed message once
+     * @function
+     * @alias subscribeOnce
+     * @param { String } message The message to subscribe to
+     * @param { Function } func The function to call when a new message is published
+     * @return { PubSub }
+     */
+    PubSub.subscribeOnce = function( message, func ){
+        var token = PubSub.subscribe( message, function(){
+            // before func apply, unsubscribe message
+            PubSub.unsubscribe( token );
+            func.apply( this, arguments );
+        });
+        return PubSub;
+    };
+
+    /**
+     * Clears all subscriptions
+     * @function
+     * @public
+     * @alias clearAllSubscriptions
+     */
+    PubSub.clearAllSubscriptions = function clearAllSubscriptions(){
+        messages = {};
+    };
+
+    /**
+     * Clear subscriptions by the topic
+     * @function
+     * @public
+     * @alias clearAllSubscriptions
+     * @return { int }
+     */
+    PubSub.clearSubscriptions = function clearSubscriptions(topic){
+        var m;
+        for (m in messages){
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0){
+                delete messages[m];
+            }
+        }
+    };
+
+    /**
+       Count subscriptions by the topic
+     * @function
+     * @public
+     * @alias countSubscriptions
+     * @return { Array }
+    */
+    PubSub.countSubscriptions = function countSubscriptions(topic){
+        var m;
+        // eslint-disable-next-line no-unused-vars
+        var token;
+        var count = 0;
+        for (m in messages) {
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0) {
+                for (token in messages[m]) {
+                    count++;
+                }
+                break;
+            }
+        }
+        return count;
+    };
+
+
+    /**
+       Gets subscriptions by the topic
+     * @function
+     * @public
+     * @alias getSubscriptions
+    */
+    PubSub.getSubscriptions = function getSubscriptions(topic){
+        var m;
+        var list = [];
+        for (m in messages){
+            if (Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0){
+                list.push(m);
+            }
+        }
+        return list;
+    };
+
+    /**
+     * Removes subscriptions
+     *
+     * - When passed a token, removes a specific subscription.
+     *
+	 * - When passed a function, removes all subscriptions for that function
+     *
+	 * - When passed a topic, removes all subscriptions for that topic (hierarchy)
+     * @function
+     * @public
+     * @alias subscribeOnce
+     * @param { String | Function } value A token, function or topic to unsubscribe from
+     * @example // Unsubscribing with a token
+     * var token = PubSub.subscribe('mytopic', myFunc);
+     * PubSub.unsubscribe(token);
+     * @example // Unsubscribing with a function
+     * PubSub.unsubscribe(myFunc);
+     * @example // Unsubscribing from a topic
+     * PubSub.unsubscribe('mytopic');
+     */
+    PubSub.unsubscribe = function(value){
+        var descendantTopicExists = function(topic) {
+                var m;
+                for ( m in messages ){
+                    if ( Object.prototype.hasOwnProperty.call(messages, m) && m.indexOf(topic) === 0 ){
+                        // a descendant of the topic exists:
+                        return true;
+                    }
+                }
+
+                return false;
+            },
+            isTopic    = typeof value === 'string' && ( Object.prototype.hasOwnProperty.call(messages, value) || descendantTopicExists(value) ),
+            isToken    = !isTopic && typeof value === 'string',
+            isFunction = typeof value === 'function',
+            result = false,
+            m, message, t;
+
+        if (isTopic){
+            PubSub.clearSubscriptions(value);
+            return;
+        }
+
+        for ( m in messages ){
+            if ( Object.prototype.hasOwnProperty.call( messages, m ) ){
+                message = messages[m];
+
+                if ( isToken && message[value] ){
+                    delete message[value];
+                    result = value;
+                    // tokens are unique, so we can just stop here
+                    break;
+                }
+
+                if (isFunction) {
+                    for ( t in message ){
+                        if (Object.prototype.hasOwnProperty.call(message, t) && message[t] === value){
+                            delete message[t];
+                            result = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    };
+}));

+ 7 - 0
node_modules/pubsub-js/test/.eslintrc.js

@@ -0,0 +1,7 @@
+module.exports = {
+	"env": {
+		"commonjs": true,
+		"mocha": true,
+		"node": true
+	}
+};

+ 55 - 0
node_modules/pubsub-js/test/helper.js

@@ -0,0 +1,55 @@
+(function(root, factory){
+    'use strict';
+
+    var define = root.define;
+
+    // CommonJS
+    if (typeof exports === 'object'){
+        module.exports = factory();
+
+        // AMD
+    } else if (typeof define === 'function' && define.amd){
+        define(factory);
+        // Browser
+    } else {
+        root.TestHelper = factory();
+    }
+}( ( typeof window === 'object' && window ) || this, function(){
+
+    'use strict';
+
+    var TestHelper = {},
+        assert = require('referee').assert;
+
+    // helps us make sure that the order of the tests have no impact on their succes
+    function getUniqueString(){
+        if ( getUniqueString.uid === undefined ){
+            getUniqueString.uid = 0;
+        }
+        getUniqueString.uid++;
+
+        return 'my unique String number ' + getUniqueString.uid.toString();
+    }
+
+    // makes sure that all tokens in the passed array are different
+    function assertAllTokensDifferent( tokens ){
+        var length = tokens.length,
+            j, k;
+        assert( tokens.length > 0 );
+        // compare all tokens
+        for ( j = 0; j < length; j++ ){
+            for ( k = j + 1; k < length; k++ ){
+                assert( tokens[j] !== tokens[k] );
+            }
+        }
+
+        // make sure we actually tested something
+        assert.equals( j, length );
+        assert.equals( k, length );
+    }
+
+    TestHelper.getUniqueString = getUniqueString;
+    TestHelper.assertAllTokensDifferent = assertAllTokensDifferent;
+
+    return TestHelper;
+}));

+ 50 - 0
node_modules/pubsub-js/test/test-bug-9.js

@@ -0,0 +1,50 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+/**
+ *	This is a test proving that bug 9 has been fixed.
+ *	See https://github.com/mroderick/PubSubJS/issues/9
+ */
+describe( 'Bug 9, publish method', function() {
+    it('should notify all subscribers in a hierarchy', function( done ){
+        var subscriber1 = sinon.spy(),
+            subscriber2 = sinon.spy(),
+            subscriber3 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( 'a.b.c', subscriber1 );
+        PubSub.subscribe( 'a.b', subscriber2 );
+        PubSub.subscribe( 'a', subscriber3 );
+
+        PubSub.publish( 'a.b.c.d' );
+
+        clock.tick(1);
+
+        assert( subscriber1.calledOnce );
+        assert( subscriber2.calledOnce );
+        assert( subscriber3.calledOnce );
+
+        done();
+        clock.restore();
+    });
+
+    it('should notify individual subscribers, even when there are no subscribers further up', function( done ){
+
+        var rootTopic = 'a.b.c',
+            subscriber = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe(rootTopic, subscriber);
+        PubSub.publish(rootTopic + '.d');
+
+        clock.tick(1);
+
+        assert( subscriber.calledOnce );
+
+        done();
+        clock.restore();
+    });
+});

+ 24 - 0
node_modules/pubsub-js/test/test-clearSubscriptions.js

@@ -0,0 +1,24 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe('clearAllSubscriptions method', function () {
+    it('must clear all subscriptions', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        PubSub.clearAllSubscriptions();
+
+        PubSub.publishSync(topic, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        refute(spy2.called);
+    });
+});

+ 32 - 0
node_modules/pubsub-js/test/test-countSubscriptions.js

@@ -0,0 +1,32 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe('test-countSubscriptions method', function () {
+    it('must be count eq 0', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+
+        var counts = PubSub.countSubscriptions(topic);
+
+        assert.equals(counts,1);
+    });
+
+    it('should count all subscriptions', function() {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        var counts = PubSub.countSubscriptions(topic);
+
+        assert.equals(counts, 2);
+    });
+});

+ 20 - 0
node_modules/pubsub-js/test/test-getSubscriptions.js

@@ -0,0 +1,20 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('./helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe('getSubscriptions method', function () {
+    it('must be length eq 0', function () {
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+
+        var subscriptions = PubSub.getSubscriptions(topic).length;
+
+        assert.equals(subscriptions,1);
+    });
+
+});

+ 204 - 0
node_modules/pubsub-js/test/test-hierarchical-addressing.js

@@ -0,0 +1,204 @@
+'use strict';
+
+var PubSub = global.PubSub || require('../src/pubsub'),
+    TestHelper = global.TestHelper || require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+describe( 'Hierarchical addressing', function () {
+    beforeEach(function(){
+        this.clock = sinon.useFakeTimers();
+    });
+
+    afterEach(function(){
+        this.clock.restore();
+    });
+
+    it('publish method should not call any children in a namespace', function( done ) {
+        var messages = ['library', 'library.music'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy );
+        PubSub.publish( messages[0], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 1 );
+
+        done();
+    });
+
+    it('publish method should call a parent namespace', function( done ) {
+        // Publishing library.music should trigger parent library
+        var messages = ['library', 'library.music'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.publish( messages[1], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('publish method should call only a parent namespace', function( done ) {
+        //Publishing library.music should only trigger parents descendants
+        //Even if it has a child
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy );
+        PubSub.publish( messages[1], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('publish method should call all parent namespaces', function( done ) {
+        //Publishing library.music.jazz should trigger all parents
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 3 );
+
+        done();
+    });
+
+    it('publish method should call only parent descendants', function( done ) {
+        //Publishing library.music.jazz should trigger only all parents descendants
+        //Skipping library.playlist and library.playlist.*
+        var messages = [
+                'library',
+                'library.music',
+                'library.music.jazz',
+                'library.playlist',
+                'library.playlist.mine'
+            ],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.subscribe( messages[3], spy );
+        PubSub.subscribe( messages[4], spy );
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 3 );
+
+        done();
+    });
+
+    it('publish method should call all parent descendants deeply', function( done ) {
+        //Publishing library.music.jazz.soft.swing should trigger all but
+        //library.music.playlist.jazz
+        var messages = [
+                'library',
+                'library.music',
+                'library.music.jazz',
+                'library.music.jazz.soft',
+                'library.music.jazz.soft.swing',
+                'library.music.playlist.jazz'
+            ],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+        PubSub.subscribe( messages[3], spy ); //This should be called
+        PubSub.subscribe( messages[4], spy ); //This should be called
+        PubSub.subscribe( messages[5], spy ); //This should be called
+        PubSub.subscribe( messages[6], spy );
+        PubSub.publish( messages[4], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 5 );
+
+        done();
+    });
+
+    it('publish method should still call all parents, even when middle child is unsubscribed', function( done ) {
+        var messages = ['library', 'library.music', 'library.music.jazz'],
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString(),
+            token;
+
+
+        PubSub.subscribe( messages[0], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+
+        token = PubSub.subscribe( messages[1], spy );
+
+        PubSub.unsubscribe( token ); //Take out middle child
+
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+
+    it('unsubscribe method should return tokens when succesfully removing namespaced message', function(){
+        var func = function(){ return undefined; },
+            messages = ['playlist.music', 'playlist.music.jazz'],
+            token1 = PubSub.subscribe( messages[0], func),
+            token2 = PubSub.subscribe( messages[1], func ),
+            result1 = PubSub.unsubscribe( token1 ),
+            result2 = PubSub.unsubscribe( token2 );
+
+        assert.equals( result1, token1 );
+        assert.equals( result2, token2 );
+    });
+
+    it('unsubscribe method should unsubscribe parent without affecting orphans', function( done ){
+        var data = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            messages = ['playlist', 'playlist.music', 'playlist.music.jazz'],
+            token;
+
+        token = PubSub.subscribe( messages[0], spy ); //Gets unsubscribed
+        PubSub.subscribe( messages[1], spy ); //This should be called
+        PubSub.subscribe( messages[2], spy ); //This should be called
+
+        PubSub.unsubscribe( token );
+
+        PubSub.publish( messages[2], data );
+
+        assert.equals( spy.callCount, 0 );
+        this.clock.tick(1);
+        assert.equals( spy.callCount, 2 );
+
+        done();
+    });
+});

+ 43 - 0
node_modules/pubsub-js/test/test-issue-54.js

@@ -0,0 +1,43 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+/**
+ *	This is a test proving that bug 54 has been fixed.
+ *	See https://github.com/mroderick/PubSubJS/issues/54
+ */
+describe( 'Issue 54, publish method', function () {
+
+    it('should notify all subscribers, even when one is unsubscribed', function( done ){
+        var topic = TestHelper.getUniqueString(),
+            token1,
+            token1Unsubscribed = false,
+            subscriber1 = function(){
+                PubSub.unsubscribe(token1);
+                token1Unsubscribed = true;
+            },
+            spy1 = sinon.spy(subscriber1),
+            spy2 = sinon.spy(),
+            spy3 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        token1 = PubSub.subscribe( topic, spy1 );
+        PubSub.subscribe( topic, spy2 );
+        PubSub.subscribe( topic, spy3 );
+
+        PubSub.publish( topic );
+
+        clock.tick(1);
+
+        assert( token1Unsubscribed === true );
+        assert( spy1.calledOnce );
+        assert( spy2.calledOnce );
+        assert( spy3.calledOnce );
+
+        done();
+        clock.restore();
+    });
+});

+ 211 - 0
node_modules/pubsub-js/test/test-publish.js

@@ -0,0 +1,211 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe( 'publish method', function () {
+    it('should return false if there are no subscribers', function(){
+        var message = TestHelper.getUniqueString();
+        assert.equals( PubSub.publish( message ), false );
+    });
+
+    it('should return true if there are subscribers to a message', function(){
+        var message = TestHelper.getUniqueString(),
+            func = function(){ return undefined; };
+
+        PubSub.subscribe( message, func );
+        assert( PubSub.publish( message ) );
+    });
+
+    it('should return false, when there are no longer any subscribers to a message', function(){
+        var message = TestHelper.getUniqueString(),
+            func = function(){ return undefined; },
+            token = PubSub.subscribe(message, func);
+
+        PubSub.unsubscribe(token);
+        assert.equals( PubSub.publish(message), false );
+    });
+
+    it('should call all subscribers for a message exactly once', function(){
+        var message = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe( message, spy1 );
+        PubSub.subscribe( message, spy2 );
+
+        PubSub.publishSync( message, 'my payload' ); // force sync here, easier to test
+
+        assert( spy1.calledOnce );
+        assert( spy2.calledOnce );
+    });
+
+    it('should call all ONLY subscribers of the published message', function(){
+        var message1 = TestHelper.getUniqueString(),
+            message2 = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe( message1, spy1 );
+        PubSub.subscribe( message2, spy2 );
+
+        PubSub.publishSync( message1, 'some payload' );
+
+        // ensure the first subscriber IS called
+        assert(	 spy1.called );
+        // ensure the second subscriber IS NOT called
+        assert.equals( spy2.callCount, 0 );
+    });
+
+    it('should call subscribers with message as first argument', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, 'some payload' );
+
+        assert( spy.calledWith( message ) );
+    });
+
+    it('should call subscribers with data as second argument', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, data );
+
+        assert( spy.calledWith( message, data ) );
+    });
+
+    it('should publish method asyncronously', function( done ){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publish( message, data );
+
+        assert.equals( spy.callCount, 0 );
+        clock.tick(1);
+        assert.equals( spy.callCount, 1 );
+
+        done();
+        clock.restore();
+    });
+
+    it('publishSync method should allow syncronous publication', function(){
+        var message = TestHelper.getUniqueString(),
+            spy = sinon.spy(),
+            data = TestHelper.getUniqueString();
+
+        PubSub.subscribe( message, spy );
+        PubSub.publishSync( message, data );
+
+        assert.equals( spy.callCount, 1 );
+    });
+
+    it('should call all subscribers, even if there are exceptions', function( done ){
+        var message = TestHelper.getUniqueString(),
+            func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy(),
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe( message, func1 );
+        PubSub.subscribe( message, spy1 );
+        PubSub.subscribe( message, spy2 );
+
+        assert.exception( function(){
+            PubSub.publishSync( message, 'some data' );
+            clock.tick(1);
+        });
+
+        assert( spy1.called );
+        assert( spy2.called );
+
+        done();
+        clock.restore();
+    });
+
+    it('should fail immediately on exceptions when immediateExceptions is true', function(){
+        var message = TestHelper.getUniqueString(),
+            func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+
+        PubSub.subscribe( message, func1 );
+        PubSub.subscribe( message, spy1 );
+
+        PubSub.immediateExceptions = true;
+
+        assert.exception( function(){
+            PubSub.publishSync( message, 'some data' );
+        });
+
+        refute( spy1.called );
+        refute( spy2.called );
+
+        // make sure we restore PubSub to it's original state
+        delete PubSub.immediateExceptions;
+    });
+
+    it('should fail immediately on exceptions in namespaces when immediateExceptions is true',  function(){
+        var func1 = function(){
+                throw('some error');
+            },
+            spy1 = sinon.spy();
+
+        PubSub.subscribe( 'buy', func1 );
+        PubSub.subscribe( 'buy', spy1 );
+
+        PubSub.immediateExceptions = true;
+
+        assert.exception( function(){
+            PubSub.publishSync( 'buy.tomatoes', 'some data' );
+        });
+
+        refute( spy1.called );
+
+        // make sure we restore PubSub to it's original state
+        delete PubSub.immediateExceptions;
+    });
+
+    it('should call all subscribers, even when there are unsubscriptions within', function(done){
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            func1 = function func1(){
+                PubSub.unsubscribe(func1);
+                spy1();
+            },
+
+            spy2 = sinon.spy(),
+            func2 = function func2(){
+                PubSub.unsubscribe(func2);
+                spy2();
+            },
+
+            clock = sinon.useFakeTimers();
+
+        PubSub.subscribe(topic, func1);
+        PubSub.subscribe(topic, func2);
+
+        PubSub.publish(topic, 'some data');
+        clock.tick(1);
+
+        assert(spy1.called, 'expected spy1 to be called');
+        assert(spy2.called, 'expected spy2 to be called');
+
+        clock.restore();
+        done();
+    });
+});

+ 92 - 0
node_modules/pubsub-js/test/test-subscribe.js

@@ -0,0 +1,92 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute;
+
+describe( 'subscribe method', function() {
+    it('should return token as String', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message , func );
+
+        assert.isString( token );
+    });
+
+    it('should return new token for several subscriptions with same function', function(){
+        var func = function(){ return undefined; },
+            tokens = [],
+            iterations = 10,
+            message = TestHelper.getUniqueString(),
+            i;
+
+        // build an array of tokens
+        for ( i = 0; i < iterations; i++ ){
+            tokens.push( PubSub.subscribe( message, func ) );
+        }
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return unique tokens for each namespaced subscription', function(){
+        var func = function(){ return undefined; },
+            tokens = [],
+            messages = ['library', 'library.music', 'library.music.jazz'],
+            i;
+
+        // build an array of tokens
+        for ( i = 0; i < messages.length; i++ ){
+            tokens.push( PubSub.subscribe( messages[i], func ) );
+        }
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return unique token for unique functions', function(){
+        var tokens = [],
+            iterations = 10,
+            message = TestHelper.getUniqueString(),
+            i;
+
+        function bakeFunc( value ){
+            return function(){
+                return value;
+            };
+        }
+
+        // build an array of tokens, passing in a different function for each subscription
+        for ( i = 0; i < iterations; i++ ){
+            tokens.push( PubSub.subscribe( message, bakeFunc( i ) ) );
+        }
+
+        // make sure all tokens are different
+        TestHelper.assertAllTokensDifferent( tokens );
+    });
+
+    it('should return false when subscriber argument is not a function', function(){
+        var invalidSubscribers = [undefined, null, 'a string', 123, [], {}, new Date()],
+            topic = TestHelper.getUniqueString(),
+            i;
+
+        for ( i = 0; i < invalidSubscribers.length; i++ ){
+            assert.equals(PubSub.subscribe(topic, invalidSubscribers[i]), false);
+        }
+
+        assert.equals(i, invalidSubscribers.length);
+    });
+
+    it('must not throw errors when publishing with invalid subscribers', function(){
+        var invalidSubscribers = [undefined, null, 'a string', 123, [], {}, new Date()],
+            topic = TestHelper.getUniqueString(),
+            i;
+
+        for (i = 0; i < invalidSubscribers.length; i++){
+            PubSub.subscribe(topic, invalidSubscribers[i]);
+        }
+
+        refute.exception(function(){
+            PubSub.publish(topic, TestHelper.getUniqueString());
+        });
+    });
+});

+ 28 - 0
node_modules/pubsub-js/test/test-subscribeAll.js

@@ -0,0 +1,28 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+
+describe( 'subscribeAll method', function() {
+
+    it('should return token as String', function(){
+        var func = function(){ return undefined; },
+            token = PubSub.subscribeAll( func );
+
+        assert.isString( token );
+    });
+
+    it('should subscribe for all messages', function() {
+        var message = TestHelper.getUniqueString(),
+            subscribeFn = sinon.spy();
+
+        PubSub.subscribeAll( subscribeFn );
+        PubSub.publishSync( message, 'some payload' );
+
+        assert( subscribeFn.calledOnce );
+    });
+
+} );

+ 32 - 0
node_modules/pubsub-js/test/test-subscribeOnce.js

@@ -0,0 +1,32 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    sinon = require('sinon');
+
+
+describe( 'subscribeOnce method', function() {
+
+    it( 'should return PubSub', function() {
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            pubSub = PubSub.subscribeOnce( message , func );
+        assert.same( pubSub, PubSub );
+    } );
+
+    it( 'must be executed only once', function() {
+
+        var topic = TestHelper.getUniqueString(),
+            spy = sinon.spy();
+        
+        PubSub.subscribeOnce( topic, spy );
+        for ( var i = 0; i < 3; i++ ) {
+            PubSub.publishSync( topic, TestHelper.getUniqueString() );
+        }
+
+        assert( spy.calledOnce );
+
+    } );
+
+} );

+ 21 - 0
node_modules/pubsub-js/test/test-symbol.js

@@ -0,0 +1,21 @@
+/* global Symbol */
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    assert = require('referee').assert;
+
+describe( 'subscribe and publish', function() {
+    before(function(){
+        if (typeof Symbol !== 'function'){
+            this.skip();
+        }
+    });
+    it('should work on Symbol() type message/topic', function(){
+        var MESSAGE = Symbol('MESSAGE');
+        var func = function(){ return undefined; };
+
+        PubSub.subscribe( MESSAGE, func );
+        
+        assert( PubSub.publish( MESSAGE ), true );
+    });
+});

+ 159 - 0
node_modules/pubsub-js/test/test-unsubscribe.js

@@ -0,0 +1,159 @@
+'use strict';
+
+var PubSub = require('../src/pubsub'),
+    TestHelper = require('../test/helper'),
+    assert = require('referee').assert,
+    refute = require('referee').refute,
+    sinon = require('sinon');
+
+describe( 'unsubscribe method', function() {
+    it('should return token when succesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message, func),
+            result = PubSub.unsubscribe( token );
+
+        assert.equals( result, token );
+    });
+
+    it('should return false when unsuccesful', function(){
+        var unknownToken = 'my unknown token',
+            result = PubSub.unsubscribe( unknownToken ),
+            func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            token = PubSub.subscribe( message, func );
+
+        // first, let's try a completely unknown token
+        assert.equals( result, false );
+
+        // now let's try unsubscribing the same method twice
+        PubSub.unsubscribe( token );
+        assert.equals( PubSub.unsubscribe( token ), false );
+    });
+
+    it('with function argument should return true when succesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            result;
+
+        PubSub.subscribe( message, func);
+        result = PubSub.unsubscribe( func );
+
+        assert.equals( result, true );
+    });
+
+    it('with function argument should return false when unsuccesful', function(){
+        var func = function(){ return undefined; },
+            message = TestHelper.getUniqueString(),
+            unknownToken = 'my unknown token',
+            result = PubSub.unsubscribe( unknownToken );
+
+        // first, let's try a completely unknown token
+
+        assert.equals( result, false );
+
+        // now let's try unsubscribing the same method twice
+        PubSub.subscribe( message, func );
+        PubSub.subscribe( message, func );
+        PubSub.subscribe( message, func );
+
+        // unsubscribe once, this should remove all subscriptions for message
+        PubSub.unsubscribe( func );
+
+        // unsubscribe again
+        assert.equals( PubSub.unsubscribe( func ), false );
+    });
+
+    it('with topic argument, must clear all exactly matched subscriptions', function(){
+        var topic = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic, spy1);
+        PubSub.subscribe(topic, spy2);
+
+        PubSub.unsubscribe(topic);
+
+        PubSub.publishSync(topic, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        refute(spy2.called);
+    });
+
+    it('with topic argument, must only clear matched subscriptions', function(){
+        var topic1 = TestHelper.getUniqueString(),
+            topic2 = TestHelper.getUniqueString(),
+            spy1 = sinon.spy(),
+            spy2 = sinon.spy();
+
+        PubSub.subscribe(topic1, spy1);
+        PubSub.subscribe(topic2, spy2);
+
+        PubSub.unsubscribe(topic1);
+
+        PubSub.publishSync(topic1, TestHelper.getUniqueString());
+        PubSub.publishSync(topic2, TestHelper.getUniqueString());
+
+        refute(spy1.called);
+        assert(spy2.called);
+    });
+
+    it('with topic argument, must clear all matched hierarchical subscriptions', function(){
+        var topic = TestHelper.getUniqueString(),
+            topicA = topic + '.a',
+            topicB = topic + '.a.b',
+            topicC = topic + '.a.b.c',
+            spyA = sinon.spy(),
+            spyB = sinon.spy(),
+            spyC = sinon.spy();
+
+        PubSub.subscribe(topicA, spyA);
+        PubSub.subscribe(topicB, spyB);
+        PubSub.subscribe(topicC, spyC);
+
+        PubSub.unsubscribe(topicB);
+
+        PubSub.publishSync(topicC, TestHelper.getUniqueString());
+
+        assert(spyA.called);
+        refute(spyB.called);
+        refute(spyC.called);
+    });
+
+    it('with parent topic argument, must clear all child subscriptions', function() {
+        var topic = TestHelper.getUniqueString(),
+            topicA = topic + '.a',
+            topicB = topic + '.a.b',
+            topicC = topic + '.a.b.c',
+            spyB = sinon.spy(),
+            spyC = sinon.spy();
+
+        // subscribe only to  children:
+        PubSub.subscribe(topicB, spyB);
+        PubSub.subscribe(topicC, spyC);
+
+        // but unsubscribe from a parent:
+        PubSub.unsubscribe(topicA);
+
+        PubSub.publishSync(topicB, TestHelper.getUniqueString());
+        PubSub.publishSync(topicC, TestHelper.getUniqueString());
+
+        refute(spyB.called);
+        refute(spyC.called);
+    });
+
+    it('must not throw exception when unsubscribing as part of publishing', function(){
+        refute.exception(function(){
+            var topic = TestHelper.getUniqueString(),
+                sub1 = function(){
+                    PubSub.unsubscribe(sub1);
+                },
+                sub2 = function(){ return undefined; };
+
+            PubSub.subscribe( topic, sub1 );
+            PubSub.subscribe( topic, sub2 );
+
+            PubSub.publishSync( topic, 'hello world!' );
+        });
+    });
+});

+ 5 - 0
package.json

@@ -0,0 +1,5 @@
+{
+  "dependencies": {
+    "pubsub-js": "^1.9.4"
+  }
+}

+ 30 - 2
vue2.0/vue高阶/2.归纳.md

@@ -1,5 +1,6 @@
 ## 组件通信
-### 1.自定义事件
+### 1.props (父子组件通信)
+### 2.自定义事件(父子组件通信)
 1. ref
     ```  
     父组件 template标签中 ref="名称<aaa>"
@@ -14,4 +15,31 @@
 
 $on 绑定事件
 $emit 监听事件
-$off 解绑事件
+$off 解绑事件
+```
+
+### 3.全局事件总线(任意组件通信)
+
+```
+new Vue({
+  render: h => h(App),
+  beforeCreate(){
+    Vue.prototype.$bus = this
+  }
+}).$mount('#app')
+```
+$on/$emit/$off
+this.$bus.$on 使用在mounted声明周期中
+this.$bus.$off 使用在beforeDestroy声明周期中
+
+### 4.消息的发布订阅(任意组件通信)
+npm install pubsub-js
+
+使用页面 import pubsub from 'pubsub-js';
+发布消息
+pubsub.subscribe()
+订阅消息
+pubsub.publish() 
+如果调用方法有传参 所传真实传参在第二个位置 详情请见Demo5.vue
+取消订阅
+pubsub.unsubscribe()

+ 7 - 1
vue2.0/vue高阶/hello_vue/src/App.vue

@@ -14,6 +14,8 @@
     <Demo3 ref="getThing"></Demo3>
     <hr>
     <Demo4 @getName="getName"></Demo4>
+    <Demo5></Demo5>
+    <Demo6></Demo6>
   </div>
 </template>
 
@@ -22,6 +24,8 @@ import Demo1 from './components/Demo1.vue';
 import Demo2 from './components/Demo2.vue';
 import Demo3 from './components/Demo3.vue';
 import Demo4 from './components/Demo4.vue';
+import Demo5 from './components/Demo5.vue';
+import Demo6 from './components/Demo6.vue';
 export default {
   name:"App",
   data() {
@@ -34,7 +38,9 @@ export default {
     Demo1,
     Demo2,
     Demo3,
-    Demo4
+    Demo4,
+    Demo5,
+    Demo6
   },
   created() {
     console.log(this.day)

+ 31 - 3
vue2.0/vue高阶/hello_vue/src/components/Demo5.vue

@@ -1,13 +1,41 @@
 <template>
-  
+  <div class="demo5">
+    我是一个大孩子了,上课不睡觉
+
+  </div>
 </template>
 
 <script>
+import pubsub from 'pubsub-js';
 export default {
+    data() {
+        return{
 
+        }
+    },
+    mounted(){
+        // 发布消息
+       this.pubId =  pubsub.subscribe("part1",this.demo1)
+        // this.$bus.$on("part1",this.demo1);
+    },
+    methods: {
+        demo1(name,address) {
+            console.log("五一去哪玩啊" + address)
+        },
+    },
+    beforeDestroy() {
+        // 取消订阅
+        pubsub.unsubscribe(this.pubId)
+        // this.$bus.$off();
+    },
 }
 </script>
 
-<style>
-
+<style lang="scss">
+.demo5 {
+    width: 300px;
+    height: 150px;
+    background: #0f0;
+    margin: 30px 0;
+}
 </style>

+ 33 - 0
vue2.0/vue高阶/hello_vue/src/components/Demo6.vue

@@ -0,0 +1,33 @@
+<template>
+  <div class="demo6">
+    今天是星期日
+    <button @click="send">发送</button>
+  </div>
+</template>
+
+<script>
+import pubsub from 'pubsub-js';
+export default {
+    data() {
+        return {
+            address:"洛阳"
+        }
+    },
+    methods:{
+        send() {
+            //订阅消息
+            pubsub.publish("part1",this.address)
+            // this.$bus.$emit("part1",this.address);
+        }
+    }
+}
+</script>
+
+<style lang="scss">
+.demo6 {
+    width: 300px;
+    height: 250px;
+    background: #ff0;
+    margin: 30px 0;
+}
+</style>

+ 3 - 0
vue2.0/vue高阶/hello_vue/src/main.js

@@ -5,4 +5,7 @@ Vue.config.productionTip = false
 
 new Vue({
   render: h => h(App),
+  beforeCreate(){
+    Vue.prototype.$bus = this
+  }
 }).$mount('#app')