Commit 73bcce880ee4047fd34a459a3f17dd5341ad3e21

Authored by luigser
0 parents

COMPONENTS

Showing 2328 changed files with 650035 additions and 0 deletions

Too many changes.

To preserve performance only 100 of 2328 files are displayed.

bower.json 0 โ†’ 100755
  1 +++ a/bower.json
  1 +{
  2 + "name": "COMPONENT",
  3 + "version": "1.0.0",
  4 + "authors": [
  5 + "Luigi Serra"
  6 + ],
  7 + "description": "Datalet and Controllet repository",
  8 + "license": "MIT",
  9 + "ignore": [
  10 + "**/.*",
  11 + "node_modules",
  12 + "bower_components",
  13 + "test",
  14 + "tests"
  15 + ],
  16 + "dependencies": {
  17 + "polymer": "Polymer/polymer#^1.0.0",
  18 + "google-map": "GoogleWebComponents/google-map#^1.0.0"
  19 + }
  20 +}
... ...
bower_components/font-roboto/.bower.json 0 โ†’ 100755
  1 +++ a/bower_components/font-roboto/.bower.json
  1 +{
  2 + "name": "font-roboto",
  3 + "version": "1.0.1",
  4 + "description": "An HTML import for Roboto",
  5 + "authors": [
  6 + "The Polymer Authors"
  7 + ],
  8 + "keywords": [
  9 + "font",
  10 + "roboto"
  11 + ],
  12 + "repository": {
  13 + "type": "git",
  14 + "url": "git://github.com/PolymerElements/font-roboto.git"
  15 + },
  16 + "main": "roboto.html",
  17 + "license": "http://polymer.github.io/LICENSE.txt",
  18 + "homepage": "https://github.com/PolymerElements/font-roboto/",
  19 + "ignore": [
  20 + "/.*"
  21 + ],
  22 + "_release": "1.0.1",
  23 + "_resolution": {
  24 + "type": "version",
  25 + "tag": "v1.0.1",
  26 + "commit": "21ce9b51a417fa9995cf6606e886aba0728f70a1"
  27 + },
  28 + "_source": "git://github.com/PolymerElements/font-roboto.git",
  29 + "_target": "^1.0.1",
  30 + "_originalSource": "PolymerElements/font-roboto"
  31 +}
0 32 \ No newline at end of file
... ...
bower_components/font-roboto/README.md 0 โ†’ 100755
  1 +++ a/bower_components/font-roboto/README.md
  1 +# font-roboto
... ...
bower_components/font-roboto/bower.json 0 โ†’ 100755
  1 +++ a/bower_components/font-roboto/bower.json
  1 +{
  2 + "name": "font-roboto",
  3 + "version": "1.0.1",
  4 + "description": "An HTML import for Roboto",
  5 + "authors": [
  6 + "The Polymer Authors"
  7 + ],
  8 + "keywords": [
  9 + "font",
  10 + "roboto"
  11 + ],
  12 + "repository": {
  13 + "type": "git",
  14 + "url": "git://github.com/PolymerElements/font-roboto.git"
  15 + },
  16 + "main": "roboto.html",
  17 + "license": "http://polymer.github.io/LICENSE.txt",
  18 + "homepage": "https://github.com/PolymerElements/font-roboto/",
  19 + "ignore": [
  20 + "/.*"
  21 + ]
  22 +}
... ...
bower_components/font-roboto/roboto.html 0 โ†’ 100755
  1 +++ a/bower_components/font-roboto/roboto.html
  1 +<!--
  2 +@license
  3 +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  4 +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  5 +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  6 +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  7 +Code distributed by Google as part of the polymer project is also
  8 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  9 +-->
  10 +<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic">
  11 +<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono:400,700">
... ...
bower_components/google-apis/.bower.json 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/.bower.json
  1 +{
  2 + "name": "google-apis",
  3 + "version": "1.1.0",
  4 + "description": "Web components to load Google API libraries",
  5 + "homepage": "https://googlewebcomponents.github.io/google-apis",
  6 + "main": "google-apis.html",
  7 + "authors": [
  8 + "Scott Miles <sjmiles@google.com>",
  9 + "Eric Bidelman <ebidel@gmail.com>"
  10 + ],
  11 + "license": "Apache2",
  12 + "ignore": [
  13 + "/.*",
  14 + "/test/"
  15 + ],
  16 + "keywords": [
  17 + "web-component",
  18 + "web-components",
  19 + "polymer",
  20 + "google",
  21 + "apis"
  22 + ],
  23 + "dependencies": {
  24 + "polymer": "Polymer/polymer#^1.0.0",
  25 + "iron-jsonp-library": "PolymerElements/iron-jsonp-library#^1.0.0"
  26 + },
  27 + "devDependencies": {
  28 + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0"
  29 + },
  30 + "_release": "1.1.0",
  31 + "_resolution": {
  32 + "type": "version",
  33 + "tag": "1.1.0",
  34 + "commit": "7fa2ff1da3d6a2bd5891b7441d89fd8ffbf0d83d"
  35 + },
  36 + "_source": "git://github.com/GoogleWebComponents/google-apis.git",
  37 + "_target": "^1.1.0",
  38 + "_originalSource": "GoogleWebComponents/google-apis"
  39 +}
0 40 \ No newline at end of file
... ...
bower_components/google-apis/LICENSE 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/LICENSE
  1 +Copyright 2015 Google Inc
  2 +
  3 +Licensed under the Apache License, Version 2.0 (the "License");
  4 +you may not use this file except in compliance with the License.
  5 +You may obtain a copy of the License at
  6 +
  7 + https://www.apache.org/licenses/LICENSE-2.0
  8 +
  9 +Unless required by applicable law or agreed to in writing, software
  10 +distributed under the License is distributed on an "AS IS" BASIS,
  11 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +See the License for the specific language governing permissions and
  13 +limitations under the License.
... ...
bower_components/google-apis/README.md 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/README.md
  1 +google-apis
  2 +===========
  3 +
  4 +See the [component landing page](https://googlewebcomponents.github.io/google-apis) for more information.
... ...
bower_components/google-apis/bower.json 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/bower.json
  1 +{
  2 + "name": "google-apis",
  3 + "version": "1.1.0",
  4 + "description": "Web components to load Google API libraries",
  5 + "homepage": "https://googlewebcomponents.github.io/google-apis",
  6 + "main": "google-apis.html",
  7 + "authors": [
  8 + "Scott Miles <sjmiles@google.com>",
  9 + "Eric Bidelman <ebidel@gmail.com>"
  10 + ],
  11 + "license": "Apache2",
  12 + "ignore": [
  13 + "/.*",
  14 + "/test/"
  15 + ],
  16 + "keywords": [
  17 + "web-component",
  18 + "web-components",
  19 + "polymer",
  20 + "google",
  21 + "apis"
  22 + ],
  23 + "dependencies": {
  24 + "polymer": "Polymer/polymer#^1.0.0",
  25 + "iron-jsonp-library": "PolymerElements/iron-jsonp-library#^1.0.0"
  26 + },
  27 + "devDependencies": {
  28 + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0"
  29 + }
  30 +}
... ...
bower_components/google-apis/demo/index.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/demo/index.html
  1 +<!doctype html>
  2 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  3 +<html>
  4 +<head>
  5 + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  6 + <title>google-apis Demo</title>
  7 + <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
  8 + <link rel="import" href="../google-apis.html">
  9 +</head>
  10 +<body>
  11 + <div id="messages"></div>
  12 +
  13 + <template id="t" is="dom-bind">
  14 +
  15 + <google-client-loader id="shortener"
  16 + name="urlshortener"
  17 + version="v1"
  18 + on-google-api-load="loadedShortener"></google-client-loader>
  19 + <google-js-api on-js-api-load="loaded"></google-js-api>
  20 + <google-plusone-api on-api-load="loaded"></google-plusone-api>
  21 + <google-realtime-api on-api-load="loaded"></google-realtime-api>
  22 + <google-maps-api on-api-load="loaded"></google-maps-api>
  23 + <google-youtube-api on-api-load="loaded"></google-youtube-api>
  24 + <google-legacy-loader on-api-load="loaded"></google-legacy-loader>
  25 +
  26 + </template>
  27 +
  28 + <script>
  29 + var t = document.querySelector('#t');
  30 +
  31 + t.loadedShortener = function(event) {
  32 + var request = event.target.api.url.get({
  33 + shortUrl: 'http://goo.gl/fbsS'
  34 + })
  35 + request.execute(function(resp) {
  36 + console.log(resp);
  37 + });
  38 + };
  39 +
  40 + t.loaded = function(e) {
  41 + document.querySelector('#messages').innerHTML +=
  42 + e.target.localName + ' loaded' + '<br>';
  43 + console.log(e.target.localName + ' loaded', event.target.api);
  44 + };
  45 + </script>
  46 +</body>
  47 +</html>
... ...
bower_components/google-apis/google-apis.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-apis.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<!-- Load all Google APIs, for backwards compatibility -->
  11 +<link rel="import" href="google-client-loader.html">
  12 +<link rel="import" href="google-legacy-loader.html">
  13 +<link rel="import" href="google-maps-api.html">
  14 +<link rel="import" href="google-plusone-api.html">
  15 +<link rel="import" href="google-realtime-api.html">
  16 +<link rel="import" href="google-youtube-api.html">
... ...
bower_components/google-apis/google-client-loader.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-client-loader.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="google-js-api.html">
  12 +
  13 +<!--
  14 +Element for loading a specific client Google API with the JavaScript client library.
  15 +
  16 +For loading `gapi.client` libraries
  17 +
  18 +##### Example
  19 +
  20 + <google-client-loader id="shortener"
  21 + name="urlshortener"
  22 + version="v1"></google-client-loader>
  23 +
  24 + <script>
  25 + var shortener = document.getElementById('shortener');
  26 + shortener.addEventListener('google-api-load', function(event) {
  27 + var request = shortener.api.url.get({
  28 + shortUrl: 'http://goo.gl/fbsS'
  29 + });
  30 + request.execute(function(resp) {
  31 + console.log(resp);
  32 + });
  33 + });
  34 + </script>
  35 +
  36 +@demo
  37 +-->
  38 +<dom-module id="google-client-loader">
  39 + <template>
  40 + <google-js-api on-js-api-load="_loadClient"></google-js-api>
  41 + </template>
  42 +</dom-module>
  43 +
  44 +<script>
  45 + (function() {
  46 + 'use strict';
  47 +
  48 + // Stores whether the API client is done loading.
  49 + var _clientLoaded = false;
  50 +
  51 + // Loaders and loading statuses for all APIs, indexed by API name.
  52 + // This helps prevent multiple loading requests being fired at the same time
  53 + // by multiple google-api-loader elements.
  54 + var _statuses = {};
  55 + var _loaders = {};
  56 +
  57 + Polymer({
  58 +
  59 + is: 'google-client-loader',
  60 +
  61 + /**
  62 + * Fired when the requested API is loaded. Override this name
  63 + * by setting `successEventName`.
  64 + * @event google-api-load
  65 + */
  66 +
  67 + /**
  68 + * Fired if an error occurs while loading the requested API. Override this name
  69 + * by setting `errorEventName`.
  70 + * @event google-api-load-error
  71 + */
  72 +
  73 + properties: {
  74 + /**
  75 + * Name of the API to load, e.g. 'urlshortener'.
  76 + *
  77 + * You can find the full list of APIs on the
  78 + * <a href="https://developers.google.com/apis-explorer"> Google APIs
  79 + * Explorer</a>.
  80 + * @required
  81 + */
  82 + name: String,
  83 +
  84 + /**
  85 + * Version of the API to load, e.g. 'v1'.
  86 + * @required
  87 + */
  88 + version: String,
  89 +
  90 + /**
  91 + * App Engine application ID for loading a Google Cloud Endpoints API.
  92 + */
  93 + appId: String,
  94 +
  95 + /**
  96 + * Root URL where to load the API from, e.g. 'http://host/apis'.
  97 + * For App Engine dev server this would be something like:
  98 + * 'http://localhost:8080/_ah/api'.
  99 + * Overrides 'appId' if both are specified.
  100 + */
  101 + apiRoot: String,
  102 +
  103 + /**
  104 + * Name of the event fired when API library is loaded.
  105 + */
  106 + successEventName: {
  107 + type: String,
  108 + value: 'google-api-load'
  109 + },
  110 +
  111 + /**
  112 + * Name of the event fired when there is an error loading the library.
  113 + */
  114 + errorEventName: {
  115 + type: String,
  116 + value: 'google-api-load-error'
  117 + }
  118 + },
  119 +
  120 + // Used to fix events potentially being fired multiple times by
  121 + // iron-jsonp-library.
  122 + _waiting: false,
  123 +
  124 + /**
  125 + * Returns the loaded API.
  126 + * @type gapi.client
  127 + */
  128 + get api() {
  129 + if (window.gapi && window.gapi.client &&
  130 + window.gapi.client[this.name]) {
  131 + return window.gapi.client[this.name];
  132 + } else {
  133 + return undefined;
  134 + }
  135 + },
  136 +
  137 + /**
  138 + * Wrapper for `gapi.auth`.
  139 + */
  140 + get auth() {
  141 + return gapi.auth;
  142 + },
  143 +
  144 + _loadClient: function() {
  145 + gapi.load('client', this._doneLoadingClient.bind(this));
  146 + },
  147 +
  148 + _handleLoadResponse: function(response) {
  149 + if (response && response.error) {
  150 + _statuses[this.name] = 'error';
  151 + this._fireError(response);
  152 + } else {
  153 + _statuses[this.name] = 'loaded';
  154 + this._fireSuccess();
  155 + }
  156 + },
  157 +
  158 + _fireSuccess: function() {
  159 + this.fire(this.successEventName,
  160 + { 'name': this.name, 'version': this.version });
  161 + },
  162 +
  163 + _fireError: function(response) {
  164 + if (response && response.error) {
  165 + this.fire(this.errorEventName, {
  166 + 'name': this.name,
  167 + 'version': this.version,
  168 + 'error': response.error });
  169 + } else {
  170 + this.fire(this.errorEventName, {
  171 + 'name': this.name,
  172 + 'version': this.version });
  173 + }
  174 + },
  175 +
  176 + _doneLoadingClient: function() {
  177 + _clientLoaded = true;
  178 + // Fix for API client load event being fired multiple times by
  179 + // iron-jsonp-library.
  180 + if (!this._waiting) {
  181 + this._loadApi();
  182 + }
  183 + },
  184 +
  185 + _createSelfRemovingListener: function(eventName) {
  186 + var handler = function () {
  187 + _loaders[this.name].removeEventListener(eventName, handler);
  188 + this._loadApi();
  189 + }.bind(this);
  190 +
  191 + return handler;
  192 + },
  193 +
  194 + _loadApi: function() {
  195 + if (_clientLoaded && this.name && this.version) {
  196 + this._waiting = false;
  197 + // Is this API already loaded?
  198 + if (_statuses[this.name] == 'loaded') {
  199 + this._fireSuccess();
  200 + // Is a different google-api-loader already loading this API?
  201 + } else if (_statuses[this.name] == 'loading') {
  202 + this._waiting = true;
  203 + _loaders[this.name].addEventListener(this.successEventName,
  204 + this._createSelfRemovingListener(this.successEventName));
  205 + _loaders[this.name].addEventListener(this.errorEventName,
  206 + this._createSelfRemovingListener(this.errorEventName));
  207 + // Did we get an error when we tried to load this API before?
  208 + } else if (_statuses[this.name] == 'error') {
  209 + this._fireError();
  210 + // Otherwise, looks like we're loading a new API.
  211 + } else {
  212 + var root;
  213 + if (this.apiRoot) {
  214 + root = this.apiRoot;
  215 + } else if (this.appId) {
  216 + root = 'https://' + this.appId + '.appspot.com/_ah/api';
  217 + }
  218 + _statuses[this.name] = 'loading';
  219 + _loaders[this.name] = this;
  220 + gapi.client.load(this.name, this.version,
  221 + this._handleLoadResponse.bind(this), root);
  222 + }
  223 + }
  224 + }
  225 + });
  226 + })();
  227 +</script>
... ...
bower_components/google-apis/google-js-api.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-js-api.html
  1 +<!--
  2 +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads Google JavaScript API `gapi`, firing the `js-api-load` event when ready.
  16 +
  17 +Any number of components can use `<google-js-api>` elements, and the library will only be loaded once.
  18 +
  19 +##### Example
  20 +
  21 + <google-js-api></google-js-api>
  22 + <script>
  23 + var api = document.querySelector('google-js-api');
  24 + api.addEventListener('js-api-load', function(e) {
  25 + console.log('API loaded', gapi);
  26 + });
  27 + < /script>
  28 +
  29 +*/
  30 + Polymer({
  31 +
  32 + is: 'google-js-api',
  33 +
  34 + behaviors: [
  35 + Polymer.IronJsonpLibraryBehavior
  36 + ],
  37 +
  38 + properties: {
  39 +
  40 + /** @private */
  41 + libraryUrl: {
  42 + type: String,
  43 + value: 'https://apis.google.com/js/api.js?onload=%%callback%%'
  44 + },
  45 +
  46 + /**
  47 + * Fired when the API library is loaded and available.
  48 + * @event js-api-load
  49 + */
  50 + /**
  51 + * Name of event fired when library is loaded and available.
  52 + */
  53 + notifyEvent: {
  54 + type: String,
  55 + value: 'js-api-load'
  56 + },
  57 + },
  58 +
  59 + get api() {
  60 + return gapi;
  61 + }
  62 +
  63 + });
  64 +</script>
... ...
bower_components/google-apis/google-legacy-loader.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-legacy-loader.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads the legacy Google JavaScript API Loader (https://developers.google.com/loader/).
  16 +
  17 +Fires `api-load` event when ready.
  18 +*/
  19 + Polymer({
  20 +
  21 + is: 'google-legacy-loader',
  22 +
  23 + behaviors: [
  24 + Polymer.IronJsonpLibraryBehavior
  25 + ],
  26 +
  27 + properties: {
  28 +
  29 + /** @private */
  30 + libraryUrl: {
  31 + type: String,
  32 + value: 'https://www.google.com/jsapi?callback=%%callback%%'
  33 + },
  34 +
  35 + /**
  36 + * Fired when the API library is loaded and available.
  37 + * @event js-api-load
  38 + */
  39 + /**
  40 + * Name of event fired when library is loaded and available.
  41 + */
  42 + notifyEvent: {
  43 + type: String,
  44 + value: 'api-load'
  45 + }
  46 + },
  47 +
  48 + /**
  49 + * Wrapper for `google` API namespace.
  50 + */
  51 + get api() {
  52 + return google;
  53 + }
  54 + });
  55 +</script>
... ...
bower_components/google-apis/google-maps-api.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-maps-api.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads the Google Maps JavaScript API, firing the `api-load` event when ready.
  16 +
  17 +#### Example
  18 +
  19 + <google-maps-api api-key="abc123" version="3.exp"></google-maps-api>
  20 + <script>
  21 + var mapsAPI = document.querySelector('google-maps-api');
  22 + mapsAPI.addEventListener('api-load', function(e) {
  23 + // this.api === google.maps
  24 + });
  25 + <script>
  26 +
  27 +Any number of components can use `<google-maps-api>` elements, and the library will only be loaded once.
  28 +
  29 +@blurb Element wrapper around Google Maps API.
  30 +
  31 + */
  32 + Polymer({
  33 +
  34 + is: 'google-maps-api',
  35 +
  36 + behaviors: [
  37 + Polymer.IronJsonpLibraryBehavior
  38 + ],
  39 +
  40 + properties: {
  41 +
  42 + /** @private */
  43 + mapsUrl: {
  44 + type: String,
  45 + value: 'https://maps.googleapis.com/maps/api/js?callback=%%callback%%'
  46 + },
  47 +
  48 + /**
  49 + * A Maps API key. To obtain an API key, see developers.google.com/maps/documentation/javascript/tutorial#api_key.
  50 + */
  51 + apiKey: {
  52 + type: String,
  53 + value: ''
  54 + },
  55 +
  56 + /**
  57 + * A Maps API for Business Client ID. To obtain a Maps API for Business Client ID, see developers.google.com/maps/documentation/business/.
  58 + * If set, a Client ID will take precedence over an API Key.
  59 + */
  60 + clientId: {
  61 + type: String,
  62 + value: ''
  63 + },
  64 +
  65 + /**
  66 + * The libraries to load with this map. For more information
  67 + * see https://developers.google.com/maps/documentation/javascript/libraries.
  68 + */
  69 + libraries: {
  70 + type: String,
  71 + value: ''
  72 + },
  73 +
  74 + /**
  75 + * Version of the Maps API to use.
  76 + */
  77 + version: {
  78 + type: String,
  79 + value: '3.exp'
  80 + },
  81 +
  82 + /**
  83 + * The localized language to load the Maps API with. For more information
  84 + * see https://developers.google.com/maps/documentation/javascript/basics#Language
  85 + *
  86 + * Note: the Maps API defaults to the preffered language setting of the browser.
  87 + * Use this parameter to override that behavior.
  88 + */
  89 + language: {
  90 + type: String,
  91 + value: ''
  92 + },
  93 + /**
  94 + * If true, sign-in is enabled.
  95 + * See https://developers.google.com/maps/documentation/javascript/signedin#enable_sign_in
  96 + */
  97 + signedIn: {
  98 + type: Boolean,
  99 + value: false
  100 + },
  101 +
  102 + /**
  103 + * Fired when the Maps API library is loaded and ready.
  104 + * @event api-load
  105 + */
  106 + /**
  107 + * Name of event fired when library is loaded and available.
  108 + */
  109 + notifyEvent: {
  110 + type: String,
  111 + value: 'api-load'
  112 + },
  113 +
  114 + /** @private */
  115 + libraryUrl: {
  116 + type: String,
  117 + computed: '_computeUrl(mapsUrl, version, libraries, apiKey, clientId, language, signedIn)'
  118 + }
  119 + },
  120 +
  121 + _computeUrl: function(mapsUrl, version, libraries, apiKey, clientId, language, signedIn) {
  122 + var url = mapsUrl + '&v=' + version;
  123 +
  124 + if (libraries) {
  125 + url += "&libraries=" + libraries;
  126 + }
  127 +
  128 + if (apiKey && !clientId) {
  129 + url += '&key=' + apiKey;
  130 + }
  131 +
  132 + if (clientId) {
  133 + url += '&client=' + clientId;
  134 + }
  135 +
  136 + if (language) {
  137 + url += '&language=' + language;
  138 + }
  139 +
  140 + if (signedIn) {
  141 + url += '&signed_in=' + signedIn;
  142 + }
  143 + return url;
  144 + },
  145 +
  146 + /**
  147 + * Provides the google.maps JS API namespace.
  148 + */
  149 + get api() {
  150 + return google.maps;
  151 + }
  152 + });
  153 +</script>
... ...
bower_components/google-apis/google-plusone-api.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-plusone-api.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads the Google+ JavaScript API, firing the `api-load` event when ready.
  16 +
  17 +Any number of components can use `<google-plusone-api>` elements, and the library will only be loaded once.
  18 +*/
  19 + Polymer({
  20 +
  21 + is: 'google-plusone-api',
  22 +
  23 + behaviors: [
  24 + Polymer.IronJsonpLibraryBehavior
  25 + ],
  26 +
  27 + properties: {
  28 +
  29 + /** @private */
  30 + libraryUrl: {
  31 + type: String,
  32 + value: 'https://apis.google.com/js/plusone.js?onload=%%callback%%'
  33 + },
  34 +
  35 + /**
  36 + * Fired when the API library is loaded and available.
  37 + * @event js-api-load
  38 + */
  39 + /**
  40 + * Name of event fired when library is loaded and available.
  41 + */
  42 + notifyEvent: {
  43 + type: String,
  44 + value: 'api-load'
  45 + }
  46 +
  47 + },
  48 +
  49 + get api() {
  50 + return gapi;
  51 + }
  52 +
  53 + });
  54 +</script>
... ...
bower_components/google-apis/google-realtime-api.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-realtime-api.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads the Google Drive Realtime API, firing the `api-load` event when ready.
  16 +
  17 +Any number of components can use `<google-realtime-api>` elements, and the library will only be loaded once.
  18 +
  19 +*/
  20 + Polymer({
  21 +
  22 + is: 'google-realtime-api',
  23 +
  24 + behaviors: [
  25 + Polymer.IronJsonpLibraryBehavior
  26 + ],
  27 +
  28 + properties: {
  29 +
  30 + /** @private */
  31 + libraryUrl: {
  32 + type: String,
  33 + value: 'https://apis.google.com/js/drive-realtime.js?onload=%%callback%%'
  34 + },
  35 +
  36 + /**
  37 + * Fired when the API library is loaded and available.
  38 + * @event api-load
  39 + */
  40 + /**
  41 + * Name of event fired when library is loaded and available.
  42 + */
  43 + notifyEvent: {
  44 + type: String,
  45 + value: 'api-load'
  46 + }
  47 +
  48 + },
  49 +
  50 + /**
  51 + * Returns `gapi.drive.realtime`
  52 + */
  53 + get api() {
  54 + return gapi.drive.realtime;
  55 + }
  56 +
  57 + });
  58 +</script>
... ...
bower_components/google-apis/google-youtube-api.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/google-youtube-api.html
  1 +<!--
  2 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  3 +This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt
  4 +The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt
  5 +The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt
  6 +Code distributed by Google as part of the polymer project is also
  7 +subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt
  8 +-->
  9 +
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="../iron-jsonp-library/iron-jsonp-library.html">
  12 +
  13 +<script>
  14 +/**
  15 +Dynamically loads the Google Youtube Iframe API, firing the `api-load` event when ready.
  16 +
  17 +Any number of components can use `<google-youtube-api>` elements, and the library will only be loaded once.
  18 +
  19 +https://developers.google.com/youtube/iframe_api_reference
  20 + */
  21 + Polymer({
  22 +
  23 + is: 'google-youtube-api',
  24 +
  25 + behaviors: [
  26 + Polymer.IronJsonpLibraryBehavior
  27 + ],
  28 +
  29 + properties: {
  30 +
  31 + /** @private */
  32 + libraryUrl: {
  33 + type: String,
  34 + value: 'https://www.youtube.com/iframe_api'
  35 + },
  36 +
  37 + /**
  38 + * Fired when the API library is loaded and available.
  39 + * @event api-load
  40 + */
  41 + /**
  42 + * Name of event fired when library loads.
  43 + */
  44 + notifyEvent: {
  45 + type: String,
  46 + value: 'api-load'
  47 + },
  48 +
  49 + callbackName: {
  50 + type: String,
  51 + value: 'onYouTubeIframeAPIReady'
  52 + }
  53 +
  54 + },
  55 +
  56 + get api() {
  57 + return YT;
  58 + }
  59 +
  60 + });
  61 +</script>
... ...
bower_components/google-apis/index.html 0 โ†’ 100755
  1 +++ a/bower_components/google-apis/index.html
  1 +<!doctype html>
  2 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  3 +<html>
  4 +<head>
  5 +
  6 + <script src="../webcomponentsjs/webcomponents-lite.js"></script>
  7 + <link rel="import" href="../iron-component-page/iron-component-page.html">
  8 +
  9 +</head>
  10 +<body>
  11 +
  12 + <iron-component-page></iron-component-page>
  13 +
  14 +</body>
  15 +</html>
... ...
bower_components/google-map/.bower.json 0 โ†’ 100755
  1 +++ a/bower_components/google-map/.bower.json
  1 +{
  2 + "name": "google-map",
  3 + "version": "1.1.0",
  4 + "description": "Google Maps web components",
  5 + "homepage": "https://googlewebcomponents.github.io/google-map",
  6 + "main": [
  7 + "google-map.html",
  8 + "google-map-search.html",
  9 + "google-map-marker.html",
  10 + "google-map-directions.html"
  11 + ],
  12 + "authors": [
  13 + "Frankie Fu <ffu@google.com>",
  14 + "Scott Miles <sjmiles@google.com>",
  15 + "Eric Bidelman <ebidel@gmail.com>"
  16 + ],
  17 + "license": "Apache-2",
  18 + "ignore": [
  19 + "/.*",
  20 + "/test/"
  21 + ],
  22 + "keywords": [
  23 + "web-component",
  24 + "web-components",
  25 + "polymer",
  26 + "google",
  27 + "apis",
  28 + "maps"
  29 + ],
  30 + "dependencies": {
  31 + "polymer": "Polymer/polymer#^1.1.0",
  32 + "google-apis": "GoogleWebComponents/google-apis#^1.1.0",
  33 + "iron-resizable-behavior": "PolymerElements/iron-resizable-behavior#^1.0.0"
  34 + },
  35 + "devDependencies": {
  36 + "web-component-tester": "*",
  37 + "iron-component-page": "PolymerElements/iron-component-page#^1.0.2"
  38 + },
  39 + "_release": "1.1.0",
  40 + "_resolution": {
  41 + "type": "version",
  42 + "tag": "1.1.0",
  43 + "commit": "c45ddfa8c48a67dda1b2237589edcd45bc3f7802"
  44 + },
  45 + "_source": "git://github.com/GoogleWebComponents/google-map.git",
  46 + "_target": "^1.0.0",
  47 + "_originalSource": "GoogleWebComponents/google-map"
  48 +}
0 49 \ No newline at end of file
... ...
bower_components/google-map/LICENSE 0 โ†’ 100755
  1 +++ a/bower_components/google-map/LICENSE
  1 +Copyright 2014 Google Inc
  2 +
  3 +Licensed under the Apache License, Version 2.0 (the "License");
  4 +you may not use this file except in compliance with the License.
  5 +You may obtain a copy of the License at
  6 +
  7 + https://www.apache.org/licenses/LICENSE-2.0
  8 +
  9 +Unless required by applicable law or agreed to in writing, software
  10 +distributed under the License is distributed on an "AS IS" BASIS,
  11 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +See the License for the specific language governing permissions and
  13 +limitations under the License.
... ...
bower_components/google-map/README.md 0 โ†’ 100755
  1 +++ a/bower_components/google-map/README.md
  1 +google-map
  2 +==========
  3 +
  4 +See the [component page](https://googlewebcomponents.github.io/google-map) for more information.
  5 +
... ...
bower_components/google-map/bower.json 0 โ†’ 100755
  1 +++ a/bower_components/google-map/bower.json
  1 +{
  2 + "name": "google-map",
  3 + "version": "1.1.0",
  4 + "description": "Google Maps web components",
  5 + "homepage": "https://googlewebcomponents.github.io/google-map",
  6 + "main": [
  7 + "google-map.html",
  8 + "google-map-search.html",
  9 + "google-map-marker.html",
  10 + "google-map-directions.html"
  11 + ],
  12 + "authors": [
  13 + "Frankie Fu <ffu@google.com>",
  14 + "Scott Miles <sjmiles@google.com>",
  15 + "Eric Bidelman <ebidel@gmail.com>"
  16 + ],
  17 + "license": "Apache-2",
  18 + "ignore": [
  19 + "/.*",
  20 + "/test/"
  21 + ],
  22 + "keywords": [
  23 + "web-component",
  24 + "web-components",
  25 + "polymer",
  26 + "google",
  27 + "apis",
  28 + "maps"
  29 + ],
  30 + "dependencies": {
  31 + "polymer": "Polymer/polymer#^1.1.0",
  32 + "google-apis": "GoogleWebComponents/google-apis#^1.1.0",
  33 + "iron-resizable-behavior": "PolymerElements/iron-resizable-behavior#^1.0.0"
  34 + },
  35 + "devDependencies": {
  36 + "web-component-tester": "*",
  37 + "iron-component-page": "PolymerElements/iron-component-page#^1.0.2"
  38 + }
  39 +}
... ...
bower_components/google-map/demo/index.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/demo/index.html
  1 +<!doctype html>
  2 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  3 +<html>
  4 +<head>
  5 + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  6 + <title>Google Map demo</title>
  7 + <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
  8 + <link rel="import" href="../google-map.html">
  9 + <link rel="import" href="../google-map-marker.html">
  10 + <link rel="import" href="../google-map-directions.html">
  11 + <style>
  12 + body {
  13 + margin: 0;
  14 + height: 100vh;
  15 + }
  16 + #controlsToggle {
  17 + position: absolute;
  18 + left: 10%;
  19 + bottom: 10%;
  20 + }
  21 + </style>
  22 +</head>
  23 +<body fullbleed>
  24 +
  25 +<!-- Note: places library needs to be loaded because we're using google-map-directions
  26 + which also loads the maps lib with the places library. -->
  27 +<google-map latitude="37.779" longitude="-122.3892" min-zoom="9" max-zoom="11"
  28 + language="en" libraries="places">
  29 + <google-map-marker latitude="37.779" longitude="-122.3892"
  30 + title="Go Giants!" draggable="true">
  31 + <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/San_Francisco_Giants_Cap_Insignia.svg/200px-San_Francisco_Giants_Cap_Insignia.svg.png" />
  32 + </google-map-marker>
  33 +</google-map>
  34 +
  35 +<google-map-directions start-address="Oakland" end-address="Mountain View"
  36 + language="en"></google-map-directions>
  37 +
  38 +<button id="controlsToggle" onclick="toggleControls()">Toggle controls</button>
  39 +
  40 +<script>
  41 + var gmap = document.querySelector('google-map');
  42 + gmap.addEventListener('api-load', function(e) {
  43 + document.querySelector('google-map-directions').map = this.map;
  44 + });
  45 +
  46 + function toggleControls() {
  47 + gmap.disableDefaultUi = !gmap.disableDefaultUi;
  48 + }
  49 +</script>
  50 +</body>
  51 +</html>
... ...
bower_components/google-map/google-map-directions.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/google-map-directions.html
  1 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  2 +
  3 +<link rel="import" href="../polymer/polymer.html">
  4 +<link rel="import" href="../google-apis/google-maps-api.html">
  5 +
  6 +<!--
  7 +Provides the Google Maps API Directions Service to provide directions
  8 +between a `startAddress` and `endAddress`.
  9 +
  10 +See https://developers.google.com/maps/documentation/javascript/directions for more
  11 +information on the API.
  12 +
  13 +#### Example:
  14 +
  15 + <template is="dom-bind">
  16 + <google-map-directions map="{{map}}"
  17 + start-address="San Francisco"
  18 + end-address="Mountain View"
  19 + travel-mode="TRANSIT"
  20 + waypoints="[{location: 'Palo Alto'}, {location: 'San Mateo'}]"></google-map-directions>
  21 + <google-map map="{{map}}" latitude="37.779"
  22 + longitude="-122.3892"></google-map>
  23 + </template>
  24 +
  25 +-->
  26 +
  27 +<dom-module id="google-map-directions">
  28 + <style>
  29 + :host {
  30 + display: none;
  31 + }
  32 + </style>
  33 + <template>
  34 + <google-maps-api
  35 + api-key="[[apiKey]]"
  36 + libraries="[[libraries]]"
  37 + language="[[language]]"
  38 + on-api-load="_mapApiLoaded"></google-maps-api>
  39 + </template>
  40 +</dom-module>
  41 +
  42 +<script>
  43 + Polymer({
  44 +
  45 + is: 'google-map-directions',
  46 +
  47 +/**
  48 +Fired whenever the directions service returns a result.
  49 +
  50 +@event google-map-response
  51 +@param {Object} detail
  52 +@param {object} detail.response The directions service response.
  53 +*/
  54 + properties: {
  55 + /**
  56 + * A Maps API key. To obtain an API key, see developers.google.com/maps/documentation/javascript/tutorial#api_key.
  57 + */
  58 + apiKey: String,
  59 +
  60 + /**
  61 + * The Google map object.
  62 + *
  63 + * @type google.maps.Map
  64 + */
  65 + map: {
  66 + type: Object,
  67 + observer: '_mapChanged'
  68 + },
  69 + /**
  70 + * Start address or latlng to get directions from.
  71 + *
  72 + * @type string|google.maps.LatLng
  73 + */
  74 + startAddress: {
  75 + type: String,
  76 + value: null
  77 + },
  78 +
  79 + /**
  80 + * End address or latlng for directions to end.
  81 + *
  82 + * @type string|google.maps.LatLng
  83 + */
  84 + endAddress: {
  85 + type: String,
  86 + value: null
  87 + },
  88 +
  89 + /**
  90 + * Travel mode to use. One of 'DRIVING', 'WALKING', 'BICYCLING', 'TRANSIT'.
  91 + */
  92 + travelMode: {
  93 + type: String,
  94 + value: 'DRIVING'
  95 + },
  96 +
  97 + /**
  98 + * Array of intermediate waypoints. Directions will be calculated
  99 + * from the origin to the destination by way of each waypoint in this array.
  100 + * The maximum allowed waypoints is 8, plus the origin, and destination.
  101 + * Maps API for Business customers are allowed 23 waypoints,
  102 + * plus the origin, and destination.
  103 + * Waypoints are not supported for transit directions. Optional.
  104 + *
  105 + * @type google.maps.DirectionsWaypoint
  106 + */
  107 + waypoints: {
  108 + type: Array,
  109 + value: function() { return []; }
  110 + },
  111 +
  112 + /**
  113 + * A comma separated list (e.g. "places,geometry") of libraries to load
  114 + * with this map. Defaults to "places". For more information see
  115 + * https://developers.google.com/maps/documentation/javascript/libraries.
  116 + *
  117 + * Note, this needs to be set to the same value as the one used on <google-map>.
  118 + * If you're overriding that element's `libraries` property, this one also
  119 + * needs to be set to the Maps API loads the library code.
  120 + */
  121 + libraries: {
  122 + type: String,
  123 + value: 'places'
  124 + },
  125 +
  126 + /**
  127 + * The localized language to load the Maps API with. For more information
  128 + * see https://developers.google.com/maps/documentation/javascript/basics#Language
  129 + *
  130 + * Note: the Maps API defaults to the preffered language setting of the browser.
  131 + * Use this parameter to override that behavior.
  132 + */
  133 + language: {
  134 + type: String,
  135 + value: null
  136 + },
  137 +
  138 + /**
  139 + * The response from the directions service.
  140 + *
  141 + */
  142 + response: {
  143 + type: Object,
  144 + observer: '_responseChanged',
  145 + notify: true
  146 + }
  147 + },
  148 +
  149 + observers: [
  150 + '_route(startAddress, endAddress, travelMode, waypoints)'
  151 + ],
  152 +
  153 + _mapApiLoaded: function() {
  154 + this._route();
  155 + },
  156 +
  157 + _responseChanged: function() {
  158 + if (this.directionsRenderer && this.response) {
  159 + this.directionsRenderer.setDirections(this.response);
  160 + }
  161 + },
  162 +
  163 + _mapChanged: function() {
  164 + if (this.map && this.map instanceof google.maps.Map) {
  165 + if (!this.directionsRenderer) {
  166 + this.directionsRenderer = new google.maps.DirectionsRenderer();
  167 + }
  168 + this.directionsRenderer.setMap(this.map);
  169 + this._responseChanged();
  170 + } else {
  171 + // If there is no more map, remove the directionsRenderer from the map and delete it.
  172 + if (this.directionsRenderer) {
  173 + this.directionsRenderer.setMap(null);
  174 + this.directionsRenderer = null;
  175 + }
  176 + }
  177 + },
  178 +
  179 + _route: function() {
  180 + // Abort attempts to _route if the API is not available yet or the
  181 + // required attributes are blank.
  182 + if (typeof google == 'undefined' || typeof google.maps == 'undefined' ||
  183 + !this.startAddress || !this.endAddress) {
  184 + return;
  185 + }
  186 +
  187 + // Construct a directionsService if necessary.
  188 + // Wait until here where the maps api has loaded and directions are actually needed.
  189 + if (!this.directionsService) {
  190 + this.directionsService = new google.maps.DirectionsService();
  191 + }
  192 +
  193 + var request = {
  194 + origin: this.startAddress,
  195 + destination: this.endAddress,
  196 + travelMode: this.travelMode,
  197 + waypoints: this.waypoints
  198 + };
  199 + this.directionsService.route(request, function(response, status) {
  200 + if (status == google.maps.DirectionsStatus.OK) {
  201 + this.response = response;
  202 + this.fire('google-map-response', {response: response});
  203 + }
  204 + }.bind(this));
  205 + }
  206 + });
  207 +</script>
... ...
bower_components/google-map/google-map-marker.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/google-map-marker.html
  1 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  2 +
  3 +<link rel="import" href="../polymer/polymer.html">
  4 +<link rel="import" href="../google-apis/google-maps-api.html">
  5 +
  6 +<!--
  7 +The `google-map-marker` element represents a map marker. It is used as a
  8 +child of `google-map`.
  9 +
  10 +<b>Example</b>:
  11 +
  12 + <google-map latitude="37.77493" longitude="-122.41942">
  13 + <google-map-marker latitude="37.779" longitude="-122.3892"
  14 + title="Go Giants!"></google-map-marker>
  15 + </google-map>
  16 +
  17 +<b>Example</b> - marker with info window (children create the window content):
  18 +
  19 + <google-map-marker latitude="37.77493" longitude="-122.41942">
  20 + <img src="image.png">
  21 + </google-map-marker>
  22 +
  23 +<b>Example</b> - a draggable marker:
  24 +
  25 + <google-map-marker latitude="37.77493" longitude="-122.41942"
  26 + draggable="true"></google-map-marker>
  27 +
  28 +<b>Example</b> - hide a marker:
  29 +
  30 + <google-map-marker latitude="37.77493" longitude="-122.41942"
  31 + hidden></google-map-marker>
  32 +
  33 +-->
  34 +
  35 +<dom-module id="google-map-marker">
  36 + <style>
  37 + :host {
  38 + display: none;
  39 + }
  40 + </style>
  41 + <template><content></content></template>
  42 +</dom-module>
  43 +
  44 +<script>
  45 +
  46 +(function() {
  47 + Polymer({
  48 +
  49 + is: 'google-map-marker',
  50 +
  51 + /**
  52 + * Fired when the marker icon was clicked. Requires the clickEvents attribute to be true.
  53 + * @param {google.maps.MouseEvent} event The mouse event.
  54 + * @event google-map-marker-click
  55 + */
  56 + /**
  57 + * Fired when the marker icon was double clicked. Requires the clickEvents attribute to be true.
  58 + * @param {google.maps.MouseEvent} event The mouse event.
  59 + * @event google-map-marker-dblclick
  60 + */
  61 + /**
  62 + * Fired for a mousedown on the marker. Requires the mouseEvents attribute to be true.
  63 + * @event google-map-marker-mousedown
  64 + * @param {google.maps.MouseEvent} event The mouse event.
  65 + */
  66 + /**
  67 + * Fired when the DOM `mousemove` event is fired on the marker. Requires the mouseEvents
  68 + * attribute to be true.
  69 + * @event google-map-marker-mousemove
  70 + * @param {google.maps.MouseEvent} event The mouse event.
  71 + */
  72 + /**
  73 + * Fired when the mouse leaves the area of the marker icon. Requires the mouseEvents attribute to be
  74 + * true.
  75 + * @event google-map-marker-mouseout
  76 + * @param {google.maps.MouseEvent} event The mouse event.
  77 + */
  78 + /**
  79 + * Fired when the mouse enters the area of the marker icon. Requires the mouseEvents attribute to be
  80 + * true.
  81 + * @event google-map-marker-mouseover
  82 + * @param {google.maps.MouseEvent} event The mouse event.
  83 + */
  84 + /**
  85 + * Fired for a mouseup on the marker. Requires the mouseEvents attribute to be true.
  86 + *
  87 + * @event google-map-marker-mouseup
  88 + * @param {google.maps.MouseEvent} event The mouse event.
  89 + */
  90 + /**
  91 + * Fired for a rightclick on the marker. Requires the clickEvents attribute to be true.
  92 + * @event google-map-marker-rightclick
  93 + * @param {google.maps.MouseEvent} event The mouse event.
  94 + */
  95 + properties: {
  96 + /**
  97 + * A Google Maps marker object.
  98 + * @type google.maps.Marker
  99 + */
  100 + marker: Object,
  101 +
  102 + /**
  103 + * The Google map object.
  104 + * @type google.maps.Map
  105 + */
  106 + map: {
  107 + type: Object,
  108 + observer: '_mapChanged'
  109 + },
  110 +
  111 + /**
  112 + * A Google Map Infowindow object.
  113 + */
  114 + info: {
  115 + type: Object,
  116 + value: null
  117 + },
  118 +
  119 + /**
  120 + * When true, marker *click events are automatically registered.
  121 + */
  122 + clickEvents: {
  123 + type: Boolean,
  124 + value: false,
  125 + observer: '_clickEventsChanged'
  126 + },
  127 +
  128 + /**
  129 + * Image URL for the marker icon.
  130 + * @type string|google.maps.Icon|google.maps.Symbol
  131 + */
  132 + icon: {
  133 + type: Object,
  134 + value: null,
  135 + observer: '_iconChanged'
  136 + },
  137 +
  138 + /**
  139 + * When true, marker mouse* events are automatically registered.
  140 + */
  141 + mouseEvents: {
  142 + type: Boolean,
  143 + value: false,
  144 + observer: '_mouseEventsChanged'
  145 + },
  146 +
  147 + /**
  148 + * Z-index for the marker icon.
  149 + */
  150 + zIndex: {
  151 + type: Number,
  152 + value: 0,
  153 + observer: '_zIndexChanged'
  154 + },
  155 +
  156 + /**
  157 + * The marker's longitude coordinate.
  158 + */
  159 + longitude: {
  160 + type: Number,
  161 + value: null,
  162 + reflectToAttribute: true
  163 + },
  164 + /**
  165 + * The marker's latitude coordinate.
  166 + */
  167 + latitude: {
  168 + type: Number,
  169 + value: null,
  170 + reflectToAttribute: true
  171 + }
  172 + },
  173 +
  174 + observers: [
  175 + '_updatePosition(latitude, longitude)'
  176 + ],
  177 +
  178 + detached: function() {
  179 + if (this.marker) {
  180 + this.marker.setMap(null);
  181 + }
  182 + if (this._contentObserver)
  183 + this._contentObserver.disconnect();
  184 + },
  185 +
  186 + attached: function() {
  187 + // If element is added back to DOM, put it back on the map.
  188 + if (this.marker) {
  189 + this.marker.setMap(this.map);
  190 + }
  191 + },
  192 +
  193 + _updatePosition: function() {
  194 + if (this.marker && this.latitude != null && this.longitude != null) {
  195 + this.marker.setPosition({
  196 + lat: parseFloat(this.latitude),
  197 + lng: parseFloat(this.longitude)
  198 + });
  199 + }
  200 + },
  201 +
  202 + _clickEventsChanged: function() {
  203 + if (this.map) {
  204 + if (this.clickEvents) {
  205 + this._forwardEvent('click');
  206 + this._forwardEvent('dblclick');
  207 + this._forwardEvent('rightclick');
  208 + } else {
  209 + this._clearListener('click');
  210 + this._clearListener('dblclick');
  211 + this._clearListener('rightclick');
  212 + }
  213 + }
  214 + },
  215 +
  216 + _mouseEventsChanged: function() {
  217 + if (this.map) {
  218 + if (this.mouseEvents) {
  219 + this._forwardEvent('mousedown');
  220 + this._forwardEvent('mousemove');
  221 + this._forwardEvent('mouseout');
  222 + this._forwardEvent('mouseover');
  223 + this._forwardEvent('mouseup');
  224 + } else {
  225 + this._clearListener('mousedown');
  226 + this._clearListener('mousemove');
  227 + this._clearListener('mouseout');
  228 + this._clearListener('mouseover');
  229 + this._clearListener('mouseup');
  230 + }
  231 + }
  232 + },
  233 +
  234 + _iconChanged: function() {
  235 + if (this.marker) {
  236 + this.marker.setIcon(this.icon);
  237 + }
  238 + },
  239 +
  240 + _zIndexChanged: function() {
  241 + if (this.marker) {
  242 + this.marker.setZIndex(this.zIndex);
  243 + }
  244 + },
  245 +
  246 + _mapChanged: function() {
  247 + // Marker will be rebuilt, so disconnect existing one from old map and listeners.
  248 + if (this.marker) {
  249 + this.marker.setMap(null);
  250 + google.maps.event.clearInstanceListeners(this.marker);
  251 + }
  252 +
  253 + if (this.map && this.map instanceof google.maps.Map) {
  254 + this._mapReady();
  255 + }
  256 + },
  257 +
  258 + _contentChanged: function() {
  259 + if (this._contentObserver)
  260 + this._contentObserver.disconnect();
  261 + // Watch for future updates.
  262 + this._contentObserver = new MutationObserver( this._contentChanged.bind(this));
  263 + this._contentObserver.observe( this, {
  264 + childList: true,
  265 + subtree: true
  266 + });
  267 +
  268 + var content = this.innerHTML.trim();
  269 + if (content) {
  270 + if (!this.info) {
  271 + // Create a new infowindow
  272 + this.info = new google.maps.InfoWindow();
  273 + this.infoHandler_ = google.maps.event.addListener(this.marker, 'click', function() {
  274 + this.info.open(this.map, this.marker);
  275 + }.bind(this));
  276 + }
  277 + this.info.setContent(content);
  278 + } else {
  279 + if (this.info) {
  280 + // Destroy the existing infowindow. It doesn't make sense to have an empty one.
  281 + google.maps.event.removeListener(this.infoHandler_);
  282 + this.info = null;
  283 + }
  284 + }
  285 + },
  286 +
  287 + _mapReady: function() {
  288 + this._listeners = {};
  289 + this.marker = new google.maps.Marker({
  290 + map: this.map,
  291 + position: {lat: this.latitude, lng: this.longitude},
  292 + title: this.title,
  293 + draggable: this.draggable,
  294 + visible: !this.hidden,
  295 + icon: this.icon,
  296 + zIndex: this.zIndex
  297 + });
  298 + this._contentChanged();
  299 + this._clickEventsChanged();
  300 + this._contentChanged();
  301 + this._mouseEventsChanged();
  302 + setupDragHandler_.bind(this)();
  303 + },
  304 +
  305 + _clearListener: function(name) {
  306 + if (this._listeners[name]) {
  307 + google.maps.event.removeListener(this._listeners[name]);
  308 + this._listeners[name] = null;
  309 + }
  310 + },
  311 +
  312 + _forwardEvent: function(name) {
  313 + this._listeners[name] = google.maps.event.addListener(this.marker, name, function(event) {
  314 + this.fire('google-map-marker-' + name, event);
  315 + }.bind(this));
  316 + },
  317 +
  318 + attributeChanged: function(attrName, oldVal, newVal) {
  319 + if (!this.marker) {
  320 + return;
  321 + }
  322 +
  323 + // Cannot use *Changed watchers for native properties.
  324 + switch (attrName) {
  325 + case 'hidden':
  326 + this.marker.setVisible(!this.hidden);
  327 + break;
  328 + case 'draggable':
  329 + this.marker.setDraggable(this.draggable);
  330 + setupDragHandler_.bind(this)();
  331 + break;
  332 + case 'title':
  333 + this.marker.setTitle(this.title);
  334 + break;
  335 + }
  336 + }
  337 + });
  338 +
  339 + function setupDragHandler_() {
  340 + if (this.draggable) {
  341 + this.dragHandler_ = google.maps.event.addListener(
  342 + this.marker, 'dragend', onDragEnd_.bind(this));
  343 + } else {
  344 + google.maps.event.removeListener(this.dragHandler_);
  345 + this.dragHandler_ = null;
  346 + }
  347 + }
  348 +
  349 + function onDragEnd_(e, details, sender) {
  350 + this.latitude = e.latLng.lat();
  351 + this.longitude = e.latLng.lng();
  352 + }
  353 +})();
  354 +</script>
... ...
bower_components/google-map/google-map-search.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/google-map-search.html
  1 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  2 +
  3 +<link rel="import" href="../polymer/polymer.html">
  4 +
  5 +<!--
  6 +`google-map-search` provides Google Maps Places API functionality.
  7 +
  8 +See https://developers.google.com/maps/documentation/javascript/places for more
  9 +information on the API.
  10 +
  11 +#### Example:
  12 +
  13 + <template is="dom-bind">
  14 + <google-map-search map="[[map]]" query="Pizza"
  15 + results="{{results}}"></google-map-search>
  16 + <google-map map="{{map}}" latitude="37.779"
  17 + longitude="-122.3892">
  18 + <template is="dom-repeat" items="{{results}}" as="marker">
  19 + <google-map-marker latitude="{{marker.latitude}}"
  20 + longitude="{{marker.longitude}}">
  21 + <h2>{{marker.name}}</h2>
  22 + <span>{{marker.formatted_address}}</span>
  23 + </google-map-marker>
  24 + </template>
  25 + </google-map>
  26 + </template>
  27 + -->
  28 +
  29 +<script>
  30 +
  31 + Polymer({
  32 +
  33 + is: 'google-map-search',
  34 +
  35 + properties: {
  36 +
  37 + /**
  38 + * The Google map object.
  39 + */
  40 + map: {
  41 + type: Object,
  42 + value: null
  43 + },
  44 +
  45 + /**
  46 + * The search query.
  47 + */
  48 + query: {
  49 + type: String,
  50 + value: null
  51 + },
  52 +
  53 + /**
  54 + * Latitude of the center of the search area.
  55 + * Ignored if `globalSearch` is true.
  56 + */
  57 + latitude: {
  58 + type: Number,
  59 + value: null
  60 + },
  61 +
  62 + /**
  63 + * Longitude of the center of the search area.
  64 + * Ignored if `globalSearch` is true.
  65 + */
  66 + longitude: {
  67 + type: Number,
  68 + value: null
  69 + },
  70 +
  71 + /**
  72 + * Search radius, in meters.
  73 + * If `latitude` and `longitude` are not specified,
  74 + * the center of the currently visible map area is used.
  75 + *
  76 + * If not set, search will be restricted to the currently visible
  77 + * map area, unless `globalSearch` is set to true.
  78 + */
  79 + radius: {
  80 + type: Number,
  81 + value: null
  82 + },
  83 +
  84 + /**
  85 + * By default, search is restricted to the currently visible map area.
  86 + * Set this to true to search everywhere.
  87 + *
  88 + * Ignored if `radius` is set.
  89 + */
  90 + globalSearch: {
  91 + type: Boolean,
  92 + value: false
  93 + },
  94 +
  95 + /**
  96 + * Space-separated list of result types.
  97 + * The search will only return results of the listed types.
  98 + * See https://developers.google.com/places/documentation/supported_types
  99 + * for a list of supported types.
  100 + * Leave empty or null to search for all result types.
  101 + */
  102 + types: {
  103 + type: String,
  104 + value: null
  105 + },
  106 +
  107 + /**
  108 + * The search results.
  109 + */
  110 + results: {
  111 + type: Array,
  112 + value: function() { return []; },
  113 + notify: true
  114 + },
  115 +
  116 + /**
  117 + * The lat/lng location.
  118 + */
  119 + location: {
  120 + type: Object,
  121 + value: null,
  122 + readyOnly: true
  123 + }
  124 + },
  125 +
  126 + observers: [
  127 + 'search(query,map,location,radius,types,globalSearch)',
  128 + '_updateLocation(latitude,longitude)'
  129 + ],
  130 +
  131 + /**
  132 + * Fired when the search element returns a result.
  133 + *
  134 + * @event google-map-search-results
  135 + * @param {Array} detail An array of search results
  136 + * @param {number} detail.latitude Latitude of the result.
  137 + * @param {number} detail.longitude Longitude of the result.
  138 + * @param {bool} detail.show Whether to show the result on the map.
  139 + */
  140 +
  141 + /**
  142 + * Perform a search using for `query` for the search term.
  143 + */
  144 + search: function() {
  145 + if (this.query && this.map) {
  146 + var places = new google.maps.places.PlacesService(this.map);
  147 +
  148 + if (this.types && typeof this.types == 'string') {
  149 + var types = this.types.split(' ');
  150 + }
  151 +
  152 + if (!this.globalSearch) {
  153 + var bounds = this.map.getBounds();
  154 + } else if (this.radius) {
  155 + var radius = this.radius;
  156 + var location = this.location ? this.location : this.map.getCenter();
  157 + }
  158 +
  159 + places.textSearch({
  160 + query: this.query,
  161 + types: types,
  162 + bounds: bounds,
  163 + radius: radius,
  164 + location: location
  165 + }, this._gotResults.bind(this));
  166 + }
  167 + },
  168 +
  169 + _gotResults: function(results, status) {
  170 + this.results = results.map(function(result) {
  171 + // obtain lat/long from geometry
  172 + result.latitude = result.geometry.location.lat();
  173 + result.longitude = result.geometry.location.lng();
  174 + return result;
  175 + });
  176 + this.fire('google-map-search-results', this.results);
  177 + },
  178 +
  179 + _updateLocation: function() {
  180 + if (!this.map) {
  181 + return;
  182 + } else if (typeof this.latitude !== 'number' || isNaN(this.latitude)) {
  183 + throw new TypeError('latitude must be a number');
  184 + } else if (typeof this.longitude !== 'number' || isNaN(this.longitude)) {
  185 + throw new TypeError('longitude must be a number');
  186 + }
  187 +
  188 + // Update location. This will trigger a new search.
  189 + this._setLocation({lat: this.latitude, lng: this.longitude});
  190 + }
  191 + });
  192 +</script>
... ...
bower_components/google-map/google-map.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/google-map.html
  1 +<!-- Copyright (c) 2015 Google Inc. All rights reserved. -->
  2 +
  3 +<link rel="import" href="../polymer/polymer.html">
  4 +<link rel="import" href="../google-apis/google-maps-api.html">
  5 +<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">
  6 +<link rel="import" href="google-map-marker.html">
  7 +<!--
  8 +The `google-map` element renders a Google Map.
  9 +
  10 +<b>Example</b>:
  11 +
  12 + <style>
  13 + google-map {
  14 + height: 600px;
  15 + }
  16 + </style>
  17 + <google-map latitude="37.77493" longitude="-122.41942"></google-map>
  18 +
  19 +<b>Example</b> - add markers to the map and ensure they're in view:
  20 +
  21 + <google-map latitude="37.77493" longitude="-122.41942" fit-to-markers>
  22 + <google-map-marker latitude="37.779" longitude="-122.3892"
  23 + draggable="true" title="Go Giants!"></google-map-marker>
  24 + <google-map-marker latitude="37.777" longitude="-122.38911"></google-map-marker>
  25 + </google-map>
  26 +
  27 +<b>Example</b>:
  28 +
  29 + <google-map disable-default-ui zoom="15"></google-map>
  30 + <script>
  31 + var map = document.querySelector('google-map');
  32 + map.latitude = 37.77493;
  33 + map.longitude = -122.41942;
  34 + map.addEventListener('google-map-ready', function(e) {
  35 + alert('Map loaded!');
  36 + });
  37 + </script>
  38 +
  39 +<b>Example</b> - with Google directions, using data-binding inside another Polymer element
  40 +
  41 + <google-map map="{{map}}" libraries="places"></google-map>
  42 + <google-map-directions map="{{map}}"
  43 + start-address="San Francisco" end-address="Mountain View">
  44 + </google-map-directions>
  45 +
  46 +@demo
  47 +-->
  48 +
  49 +<dom-module id="google-map">
  50 +
  51 + <style>
  52 + :host {
  53 + position: relative;
  54 + display: block;
  55 + height: 100%;
  56 + }
  57 +
  58 + #map {
  59 + position: absolute;
  60 + top: 0;
  61 + right: 0;
  62 + bottom: 0;
  63 + left: 0;
  64 + }
  65 +
  66 + </style>
  67 + <template>
  68 + <google-maps-api id="api"
  69 + api-key="[[apiKey]]"
  70 + client-id="[[clientId]]"
  71 + version="[[version]]"
  72 + libraries="[[libraries]]"
  73 + signed-in="[[signedIn]]"
  74 + language="[[language]]"
  75 + on-api-load="_mapApiLoaded"></google-maps-api>
  76 +
  77 + <div id="map"></div>
  78 +
  79 + <content id="markers" select="google-map-marker"></content>
  80 +
  81 + </template>
  82 +</dom-module>
  83 +
  84 +<script>
  85 +
  86 + Polymer({
  87 +
  88 + is: 'google-map',
  89 +
  90 +
  91 + /**
  92 + * Fired when the Maps API has fully loaded.
  93 + * @event google-map-ready
  94 + */
  95 + /**
  96 + * Fired when the when the user clicks on the map (but not when they click on a marker, infowindow, or
  97 + * other object). Requires the clickEvents attribute to be true.
  98 + * @event google-map-click
  99 + * @param {google.maps.MouseEvent} event The mouse event.
  100 + */
  101 + /**
  102 + * Fired when the user double-clicks on the map. Note that the google-map-click event will also fire,
  103 + * right before this one. Requires the clickEvents attribute to be true.
  104 + * @event google-map-dblclick
  105 + * @param {google.maps.MouseEvent} event The mouse event.
  106 + */
  107 + /**
  108 + * Fired repeatedly while the user drags the map. Requires the dragEvents attribute to be true.
  109 + * @event google-map-drag
  110 + */
  111 + /**
  112 + * Fired when the user stops dragging the map. Requires the dragEvents attribute to be true.
  113 + * @event google-map-dragend
  114 + */
  115 + /**
  116 + * Fired when the user starts dragging the map. Requires the dragEvents attribute to be true.
  117 + * @event google-map-dragstart
  118 + */
  119 + /**
  120 + * Fired whenever the user's mouse moves over the map container. Requires the mouseEvents attribute to
  121 + * be true.
  122 + * @event google-map-mousemove
  123 + * @param {google.maps.MouseEvent} event The mouse event.
  124 + */
  125 + /**
  126 + * Fired when the user's mouse exits the map container. Requires the mouseEvents attribute to be true.
  127 + * @event google-map-mouseout
  128 + * @param {google.maps.MouseEvent} event The mouse event.
  129 + */
  130 + /**
  131 + * Fired when the user's mouse enters the map container. Requires the mouseEvents attribute to be true.
  132 + * @event google-map-mouseover
  133 + * @param {google.maps.MouseEvent} event The mouse event.
  134 + */
  135 + /**
  136 + * Fired when the DOM `contextmenu` event is fired on the map container. Requires the clickEvents
  137 + * attribute to be true.
  138 + * @event google-map-rightclick
  139 + * @param {google.maps.MouseEvent} event The mouse event.
  140 + */
  141 + properties: {
  142 + /**
  143 + * A Maps API key. To obtain an API key, see developers.google.com/maps/documentation/javascript/tutorial#api_key.
  144 + */
  145 + apiKey: String,
  146 +
  147 + /**
  148 + * A Maps API for Business Client ID. To obtain a Maps API for Business Client ID, see developers.google.com/maps/documentation/business/.
  149 + * If set, a Client ID will take precedence over an API Key.
  150 + */
  151 + clientId: String,
  152 +
  153 + /**
  154 + * A latitude to center the map on.
  155 + */
  156 + latitude: {
  157 + type: Number,
  158 + value: 37.77493,
  159 + notify: true,
  160 + reflectToAttribute: true
  161 + },
  162 +
  163 + /**
  164 + * A Maps API object.
  165 + */
  166 + map: {
  167 + type: Object,
  168 + notify: true,
  169 + value: null
  170 + },
  171 +
  172 + /**
  173 + * A comma separated list (e.g. "places,geometry") of libraries to load
  174 + * with this map. Defaults to "". For more information see
  175 + * https://developers.google.com/maps/documentation/javascript/libraries.
  176 + */
  177 + libraries: {
  178 + type: String,
  179 + value: ''
  180 + },
  181 +
  182 + /**
  183 + * A longitude to center the map on.
  184 + */
  185 + longitude: {
  186 + type: Number,
  187 + value: -122.41942,
  188 + notify: true,
  189 + reflectToAttribute: true
  190 + },
  191 +
  192 + /**
  193 + * A kml file to load.
  194 + */
  195 + kml: {
  196 + type: String,
  197 + value: null,
  198 + observer: '_loadKml'
  199 + },
  200 +
  201 + /**
  202 + * A zoom level to set the map to.
  203 + */
  204 + zoom: {
  205 + type: Number,
  206 + value: 10,
  207 + observer: '_zoomChanged'
  208 + },
  209 +
  210 + /**
  211 + * When set, prevents the map from tilting (when the zoom level and viewport supports it).
  212 + */
  213 + noAutoTilt: {
  214 + type: Boolean,
  215 + value: false
  216 + },
  217 +
  218 + /**
  219 + * Map type to display. One of 'roadmap', 'satellite', 'hybrid', 'terrain'.
  220 + */
  221 + mapType: {
  222 + type: String,
  223 + value: 'roadmap', // roadmap, satellite, hybrid, terrain,
  224 + observer: '_mapTypeChanged'
  225 + },
  226 +
  227 + /**
  228 + * Version of the Google Maps API to use.
  229 + */
  230 + version: {
  231 + type: String,
  232 + value: '3.exp'
  233 + },
  234 +
  235 + /**
  236 + * If set, removes the map's default UI controls.
  237 + */
  238 + disableDefaultUi: {
  239 + type: Boolean,
  240 + value: false,
  241 + observer: '_disableDefaultUiChanged'
  242 + },
  243 +
  244 + /**
  245 + * If set, the zoom level is set such that all markers (google-map-marker children) are brought into view.
  246 + */
  247 + fitToMarkers: {
  248 + type: Boolean,
  249 + value: false,
  250 + observer: '_fitToMarkersChanged'
  251 + },
  252 +
  253 + /**
  254 + * If true, prevent the user from zooming the map interactively.
  255 + */
  256 + disableZoom: {
  257 + type: Boolean,
  258 + value: false,
  259 + observer: '_disableZoomChanged'
  260 + },
  261 +
  262 + /**
  263 + * If set, custom styles can be applied to the map.
  264 + * For style documentation see developers.google.com/maps/documentation/javascript/reference#MapTypeStyle
  265 + */
  266 + styles: {
  267 + type: Object,
  268 + value: function() { return {}; }
  269 + },
  270 +
  271 + /**
  272 + * A maximum zoom level which will be displayed on the map.
  273 + */
  274 + maxZoom: {
  275 + type: Number,
  276 + observer: '_maxZoomChanged'
  277 + },
  278 +
  279 + /**
  280 + * A minimum zoom level which will be displayed on the map.
  281 + */
  282 + minZoom: {
  283 + type: Number,
  284 + observer: '_minZoomChanged'
  285 + },
  286 +
  287 + /**
  288 + * If true, sign-in is enabled.
  289 + * See https://developers.google.com/maps/documentation/javascript/signedin#enable_sign_in
  290 + */
  291 + signedIn: {
  292 + type: Boolean,
  293 + value: false
  294 + },
  295 +
  296 + /**
  297 + * The localized language to load the Maps API with. For more information
  298 + * see https://developers.google.com/maps/documentation/javascript/basics#Language
  299 + *
  300 + * Note: the Maps API defaults to the preffered language setting of the browser.
  301 + * Use this parameter to override that behavior.
  302 + */
  303 + language: {
  304 + type: String
  305 + },
  306 +
  307 + /**
  308 + * When true, map *click events are automatically registered.
  309 + */
  310 + clickEvents: {
  311 + type: Boolean,
  312 + value: false,
  313 + observer: '_clickEventsChanged'
  314 + },
  315 +
  316 + /**
  317 + * When true, map drag* events are automatically registered.
  318 + */
  319 + dragEvents: {
  320 + type: Boolean,
  321 + value: false,
  322 + observer: '_dragEventsChanged'
  323 + },
  324 +
  325 + /**
  326 + * When true, map mouse* events are automatically registered.
  327 + */
  328 + mouseEvents: {
  329 + type: Boolean,
  330 + value: false,
  331 + observer: '_mouseEventsChanged'
  332 + },
  333 +
  334 + /**
  335 + * Additional map options for google.maps.Map constructor.
  336 + * Use to specify additional options we do not expose as
  337 + * properties.
  338 + * Ex: `<google-map additional-map-options='{"mapTypeId":"satellite"}'>`
  339 + */
  340 + additionalMapOptions: {
  341 + type: Object,
  342 + value: function() { return {}; }
  343 + },
  344 +
  345 + /**
  346 + * The markers on the map.
  347 + */
  348 + markers: {
  349 + type: Array,
  350 + value: function() { return []; },
  351 + readOnly: true
  352 + }
  353 +
  354 + },
  355 +
  356 + behaviors: [
  357 + Polymer.IronResizableBehavior
  358 + ],
  359 +
  360 + listeners: {
  361 + 'iron-resize': 'resize'
  362 + },
  363 +
  364 + observers: [
  365 + '_debounceUpdateCenter(latitude, longitude)'
  366 + ],
  367 +
  368 + attached: function() {
  369 + this._initGMap();
  370 + },
  371 +
  372 + detached: function() {
  373 + if (this._mutationObserver) {
  374 + this._mutationObserver.disconnect();
  375 + this._mutationObserver = null;
  376 + }
  377 + },
  378 +
  379 + _initGMap: function() {
  380 + if (this.map) {
  381 + return; // already initialized
  382 + }
  383 + if (this.$.api.libraryLoaded !== true) {
  384 + return; // api not loaded
  385 + }
  386 + if (!this.isAttached) {
  387 + return; // not attached
  388 + }
  389 +
  390 + this.map = new google.maps.Map(this.$.map, this._getMapOptions());
  391 + this._listeners = {};
  392 + this._updateCenter();
  393 + this._loadKml();
  394 + this._updateMarkers();
  395 + this._addMapListeners();
  396 + this.fire('google-map-ready');
  397 + },
  398 +
  399 + _mapApiLoaded: function() {
  400 + this._initGMap();
  401 + },
  402 +
  403 + _getMapOptions: function() {
  404 + var mapOptions = {
  405 + zoom: this.zoom,
  406 + tilt: this.noAutoTilt ? 0 : 45,
  407 + mapTypeId: this.mapType,
  408 + disableDefaultUI: this.disableDefaultUi,
  409 + disableDoubleClickZoom: this.disableZoom,
  410 + scrollwheel: !this.disableZoom,
  411 + styles: this.styles,
  412 + maxZoom: Number(this.maxZoom),
  413 + minZoom: Number(this.minZoom)
  414 + };
  415 +
  416 + // Only override the default if set.
  417 + // We use getAttribute here because the default value of this.draggable = false even when not set.
  418 + if (this.getAttribute('draggable') != null) {
  419 + mapOptions.draggable = this.draggable
  420 + }
  421 + for (var p in this.additionalMapOptions)
  422 + mapOptions[p] = this.additionalMapOptions[p];
  423 +
  424 + return mapOptions;
  425 + },
  426 +
  427 + // watch for future updates
  428 + _observeMarkers: function() {
  429 + // Watch for future updates.
  430 + if (this._mutationObserver) {
  431 + return;
  432 + }
  433 + this._mutationObserver = new MutationObserver( this._updateMarkers.bind(this));
  434 + this._mutationObserver.observe(this, {
  435 + childList: true
  436 + });
  437 + },
  438 +
  439 + _updateMarkers: function() {
  440 + var newMarkers = Array.prototype.slice.call(
  441 + Polymer.dom(this.$.markers).getDistributedNodes());
  442 +
  443 + // do not recompute if markers have not been added or removed
  444 + if (newMarkers.length === this.markers.length) {
  445 + var added = newMarkers.filter(function(m) {
  446 + return this.markers && this.markers.indexOf(m) === -1;
  447 + }.bind(this));
  448 + if (added.length === 0) {
  449 + // set up observer first time around
  450 + if (!this._mutationObserver) {
  451 + this._observeMarkers();
  452 + }
  453 + return;
  454 + }
  455 + }
  456 +
  457 + this._observeMarkers();
  458 +
  459 + this.markers = this._setMarkers(newMarkers);
  460 +
  461 + // Set the map on each marker and zoom viewport to ensure they're in view.
  462 + if (this.markers.length && this.map) {
  463 + for (var i = 0, m; m = this.markers[i]; ++i) {
  464 + m.map = this.map;
  465 + }
  466 + }
  467 + if (this.fitToMarkers) {
  468 + this._fitToMarkersChanged();
  469 + }
  470 + },
  471 +
  472 + /**
  473 + * Clears all markers from the map.
  474 + *
  475 + * @method clear
  476 + */
  477 + clear: function() {
  478 + for (var i = 0, m; m = this.markers[i]; ++i) {
  479 + m.marker.setMap(null);
  480 + }
  481 + },
  482 +
  483 + /**
  484 + * Explicitly resizes the map, updating its center. This is useful if the
  485 + * map does not show after you have unhidden it.
  486 + *
  487 + * @method resize
  488 + */
  489 + resize: function() {
  490 + if (this.map) {
  491 +
  492 + // saves and restores latitude/longitude because resize can move the center
  493 + var oldLatitude = this.latitude;
  494 + var oldLongitude = this.longitude;
  495 + google.maps.event.trigger(this.map, 'resize');
  496 + this.latitude = oldLatitude; // restore because resize can move our center
  497 + this.longitude = oldLongitude;
  498 +
  499 + if (this.fitToMarkers) { // we might not have a center if we are doing fit-to-markers
  500 + this._fitToMarkersChanged();
  501 + }
  502 + }
  503 + },
  504 +
  505 + _loadKml: function() {
  506 + if (this.kml) {
  507 + var kmlfile = new google.maps.KmlLayer({
  508 + url: this.kml,
  509 + map: this.map
  510 + });
  511 + }
  512 + },
  513 +
  514 + _debounceUpdateCenter: function() {
  515 + this.debounce('updateCenter', this._updateCenter);
  516 + },
  517 +
  518 + _updateCenter: function() {
  519 + this.cancelDebouncer('updateCenter');
  520 +
  521 + if (this.map && this.latitude !== undefined && this.longitude !== undefined) {
  522 + // allow for latitude and longitude to be String-typed, but still Number valued
  523 + var lati = Number(this.latitude);
  524 + if (isNaN(lati)) {
  525 + throw new TypeError('latitude must be a number');
  526 + }
  527 + var longi = Number(this.longitude);
  528 + if (isNaN(longi)) {
  529 + throw new TypeError('longitude must be a number');
  530 + }
  531 +
  532 + var newCenter = new google.maps.LatLng(lati, longi);
  533 + var oldCenter = this.map.getCenter();
  534 +
  535 + if (!oldCenter) {
  536 + // If the map does not have a center, set it right away.
  537 + this.map.setCenter(newCenter);
  538 + } else {
  539 + // Using google.maps.LatLng returns corrected lat/lngs.
  540 + oldCenter = new google.maps.LatLng(oldCenter.lat(), oldCenter.lng());
  541 +
  542 + // If the map currently has a center, slowly pan to the new one.
  543 + if (!oldCenter.equals(newCenter)) {
  544 + this.map.panTo(newCenter);
  545 + }
  546 + }
  547 + }
  548 + },
  549 +
  550 + _zoomChanged: function() {
  551 + if (this.map) {
  552 + this.map.setZoom(Number(this.zoom));
  553 + }
  554 + },
  555 +
  556 + _clickEventsChanged: function() {
  557 + if (this.map) {
  558 + if (this.clickEvents) {
  559 + this._forwardEvent('click');
  560 + this._forwardEvent('dblclick');
  561 + this._forwardEvent('rightclick');
  562 + } else {
  563 + this._clearListener('click');
  564 + this._clearListener('dblclick');
  565 + this._clearListener('rightclick');
  566 + }
  567 + }
  568 + },
  569 +
  570 + _dragEventsChanged: function() {
  571 + if (this.map) {
  572 + if (this.dragEvents) {
  573 + this._forwardEvent('drag');
  574 + this._forwardEvent('dragend');
  575 + this._forwardEvent('dragstart');
  576 + } else {
  577 + this._clearListener('drag');
  578 + this._clearListener('dragend');
  579 + this._clearListener('dragstart');
  580 + }
  581 + }
  582 + },
  583 +
  584 + _mouseEventsChanged: function() {
  585 + if (this.map) {
  586 + if (this.mouseEvents) {
  587 + this._forwardEvent('mousemove');
  588 + this._forwardEvent('mouseout');
  589 + this._forwardEvent('mouseover');
  590 + } else {
  591 + this._clearListener('mousemove');
  592 + this._clearListener('mouseout');
  593 + this._clearListener('mouseover');
  594 + }
  595 + }
  596 + },
  597 +
  598 + _maxZoomChanged: function() {
  599 + if (this.map) {
  600 + this.map.setOptions({maxZoom: Number(this.maxZoom)});
  601 + }
  602 + },
  603 +
  604 + _minZoomChanged: function() {
  605 + if (this.map) {
  606 + this.map.setOptions({minZoom: Number(this.minZoom)});
  607 + }
  608 + },
  609 +
  610 + _mapTypeChanged: function() {
  611 + if (this.map) {
  612 + this.map.setMapTypeId(this.mapType);
  613 + }
  614 + },
  615 +
  616 + _disableDefaultUiChanged: function() {
  617 + if (!this.map) {
  618 + return;
  619 + }
  620 + this.map.setOptions({disableDefaultUI: this.disableDefaultUi});
  621 + },
  622 +
  623 + _disableZoomChanged: function() {
  624 + if (!this.map) {
  625 + return;
  626 + }
  627 + this.map.setOptions({
  628 + disableDoubleClickZoom: this.disableZoom,
  629 + scrollwheel: !this.disableZoom
  630 + });
  631 + },
  632 +
  633 + attributeChanged: function(attrName, oldVal, newVal) {
  634 + if (!this.map) {
  635 + return;
  636 + }
  637 + // Cannot use *Changed watchers for native properties.
  638 + switch (attrName) {
  639 + case 'draggable':
  640 + this.map.setOptions({draggable: this.draggable});
  641 + break;
  642 + }
  643 + },
  644 +
  645 + _fitToMarkersChanged: function() {
  646 + // TODO(ericbidelman): respect user's zoom level.
  647 +
  648 + if (this.map && this.fitToMarkers) {
  649 + var latLngBounds = new google.maps.LatLngBounds();
  650 + for (var i = 0, m; m = this.markers[i]; ++i) {
  651 + latLngBounds.extend(
  652 + new google.maps.LatLng(m.latitude, m.longitude));
  653 + }
  654 +
  655 + // For one marker, don't alter zoom, just center it.
  656 + if (this.markers.length > 1) {
  657 + this.map.fitBounds(latLngBounds);
  658 + }
  659 +
  660 + this.map.setCenter(latLngBounds.getCenter());
  661 + }
  662 + },
  663 +
  664 + _addMapListeners: function() {
  665 + google.maps.event.addListener(this.map, 'center_changed', function() {
  666 + var center = this.map.getCenter();
  667 + this.latitude = center.lat();
  668 + this.longitude = center.lng();
  669 + }.bind(this));
  670 +
  671 + google.maps.event.addListener(this.map, 'zoom_changed', function() {
  672 + this.zoom = this.map.getZoom();
  673 + }.bind(this));
  674 +
  675 + this._clickEventsChanged();
  676 + this._dragEventsChanged();
  677 + this._mouseEventsChanged();
  678 + },
  679 +
  680 + _clearListener: function(name) {
  681 + if (this._listeners[name]) {
  682 + google.maps.event.removeListener(this._listeners[name]);
  683 + this._listeners[name] = null;
  684 + }
  685 + },
  686 +
  687 + _forwardEvent: function(name) {
  688 + this._listeners[name] = google.maps.event.addListener(this.map, name, function(event) {
  689 + this.fire('google-map-' + name, event);
  690 + }.bind(this));
  691 + }
  692 +
  693 + });
  694 +
  695 +</script>
... ...
bower_components/google-map/index.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/index.html
  1 +<!doctype html>
  2 +<!-- Copyright (c) 2014 Google Inc. All rights reserved. -->
  3 +<html>
  4 +<head>
  5 +
  6 + <script src="../webcomponentsjs/webcomponents-lite.js"></script>
  7 + <link rel="import" href="../iron-component-page/iron-component-page.html">
  8 +
  9 +</head>
  10 +<body>
  11 +<!-- FIXME rename sources to src,no multiple sources in iron-component-page yet-->
  12 + <iron-component-page sources='["google-map.html", "google-map-directions.html", "google-map-search.html"]'></iron-component-page>
  13 +</body>
  14 +</html>
... ...
bower_components/google-map/metadata.html 0 โ†’ 100755
  1 +++ a/bower_components/google-map/metadata.html
  1 +<x-meta id="google-map" label="Google Map">
  2 + <template>
  3 + <google-map style="width: 400px; height: 400px; display: block;"></google-map>
  4 + </template>
  5 + <property name="mapType" kind="select" options="roadmap,satellite,hybrid,terrain"></property>
  6 + <template id="imports">
  7 + <link rel="import" href="google-map.html">
  8 + </template>
  9 +</x-meta>
  10 +
  11 +<x-meta id="google-map-directions" label="Google Map Directions">
  12 + <template>
  13 + <google-map-directions></google-map-directions>
  14 + </template>
  15 + <property name="map" kind="string"></property>
  16 + <property name="travelMode" kind="select" options="DRIVING,TRANSIT,WALKING,BICYCLING"></property>
  17 + <template id="imports">
  18 + <link rel="import" href="google-map-directions.html">
  19 + </template>
  20 +</x-meta>
  21 +
  22 +<x-meta id="google-map-search" label="Google Map Search">
  23 + <template>
  24 + <google-map-search></google-map-search>
  25 + </template>
  26 + <property name="map" kind="string"></property>
  27 + <property name="query" kind="string"></property>
  28 + <template id="imports">
  29 + <link rel="import" href="google-map-search.html">
  30 + </template>
  31 +</x-meta>
... ...
bower_components/hydrolysis/.bower.json 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/.bower.json
  1 +{
  2 + "name": "hydrolysis",
  3 + "main": "hydrolysis.js",
  4 + "ignore": [
  5 + "lib/",
  6 + "examples/",
  7 + "demo/",
  8 + "test/",
  9 + ".gitignore",
  10 + "gulpfile.js",
  11 + "package.json"
  12 + ],
  13 + "repository": {
  14 + "type": "git",
  15 + "url": "git://github.com/Polymer/hydrolysis.git"
  16 + },
  17 + "devDependencies": {
  18 + "polymer": "Polymer/polymer#^0.9.0",
  19 + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
  20 + "web-component-tester": "*"
  21 + },
  22 + "version": "1.15.2",
  23 + "homepage": "https://github.com/Polymer/hydrolysis",
  24 + "_release": "1.15.2",
  25 + "_resolution": {
  26 + "type": "version",
  27 + "tag": "v1.15.2",
  28 + "commit": "3b255182fd39a273c255ac2a49db8d06d96f667d"
  29 + },
  30 + "_source": "git://github.com/Polymer/hydrolysis.git",
  31 + "_target": "^1.11",
  32 + "_originalSource": "Polymer/hydrolysis"
  33 +}
0 34 \ No newline at end of file
... ...
bower_components/hydrolysis/.editorconfig 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/.editorconfig
  1 +# Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  2 +# This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  3 +# The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  4 +# The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  5 +# Code distributed by Google as part of the polymer project is also
  6 +# subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  7 +
  8 +# Polymer EditorConfig
  9 +
  10 +root = true
  11 +
  12 +[*]
  13 +charset = utf-8
  14 +indent_size = 2
  15 +indent_style = space
  16 +trim_trailing_whitespace = true
  17 +
  18 +[*.md]
  19 +trim_trailing_whitespace = false
0 20 \ No newline at end of file
... ...
bower_components/hydrolysis/.gitattributes 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/.gitattributes
  1 +* text=auto
... ...
bower_components/hydrolysis/API.md 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/API.md
  1 +## Objects
  2 +<dl>
  3 +<dt><a href="#hydrolysis">hydrolysis</a> : <code>object</code></dt>
  4 +<dd><p>Static analysis for Polymer.</p>
  5 +</dd>
  6 +</dl>
  7 +## Functions
  8 +<dl>
  9 +<dt><a href="#isSiblingOrAunt">isSiblingOrAunt()</a> โ‡’ <code>boolean</code></dt>
  10 +<dd><p>Returns true if <code>patha</code> is a sibling or aunt of <code>pathb</code>.</p>
  11 +</dd>
  12 +<dt><a href="#redirectSibling">redirectSibling()</a> โ‡’ <code>string</code></dt>
  13 +<dd><p>Change <code>localPath</code> from a sibling of <code>basePath</code> to be a child of
  14 +<code>basePath</code> joined with <code>redirect</code>.</p>
  15 +</dd>
  16 +</dl>
  17 +<a name="hydrolysis"></a>
  18 +## hydrolysis : <code>object</code>
  19 +Static analysis for Polymer.
  20 +
  21 +**Kind**: global namespace
  22 +
  23 +* [hydrolysis](#hydrolysis) : <code>object</code>
  24 + * [.Analyzer](#hydrolysis.Analyzer)
  25 + * [new Analyzer(attachAST, [loader])](#new_hydrolysis.Analyzer_new)
  26 + * _instance_
  27 + * [.elements](#hydrolysis.Analyzer#elements) : <code>Array.&lt;ElementDescriptor&gt;</code>
  28 + * [.elementsByTagName](#hydrolysis.Analyzer#elementsByTagName) : <code>Object.&lt;string, ElementDescriptor&gt;</code>
  29 + * [.features](#hydrolysis.Analyzer#features) : <code>Array.&lt;FeatureDescriptor&gt;</code>
  30 + * [.behaviors](#hydrolysis.Analyzer#behaviors) : <code>Array.&lt;BehaviorDescriptor&gt;</code>
  31 + * [.html](#hydrolysis.Analyzer#html) : <code>Object.&lt;string, AnalyzedDocument&gt;</code>
  32 + * [.parsedDocuments](#hydrolysis.Analyzer#parsedDocuments) : <code>Object</code>
  33 + * [._getDependencies(href, [found], [transitive])](#hydrolysis.Analyzer#_getDependencies) โ‡’ <code>Array.&lt;string&gt;</code>
  34 + * [.metadataTree(href)](#hydrolysis.Analyzer#metadataTree) โ‡’ <code>Promise</code>
  35 + * [.nodeWalkDocuments(predicate)](#hydrolysis.Analyzer#nodeWalkDocuments) โ‡’ <code>Object</code>
  36 + * [.annotate()](#hydrolysis.Analyzer#annotate)
  37 + * [.clean()](#hydrolysis.Analyzer#clean)
  38 + * _static_
  39 + * [.analyze(href, [options])](#hydrolysis.Analyzer.analyze) โ‡’ <code>Promise.&lt;Analyzer&gt;</code>
  40 + * [.FileLoader](#hydrolysis.FileLoader)
  41 + * [new FileLoader()](#new_hydrolysis.FileLoader_new)
  42 + * [.addResolver(resolver)](#hydrolysis.FileLoader#addResolver)
  43 + * [.request(url)](#hydrolysis.FileLoader#request) โ‡’ <code>Promise.&lt;string&gt;</code>
  44 + * [.FSResolver](#hydrolysis.FSResolver)
  45 + * [new FSResolver(config)](#new_hydrolysis.FSResolver_new)
  46 + * [.NoopResolver](#hydrolysis.NoopResolver)
  47 + * [new NoopResolver(config)](#new_hydrolysis.NoopResolver_new)
  48 + * [.accept(uri, deferred)](#hydrolysis.NoopResolver#accept) โ‡’ <code>boolean</code>
  49 + * [.XHRResolver](#hydrolysis.XHRResolver)
  50 + * [new XHRResolver(config)](#new_hydrolysis.XHRResolver_new)
  51 + * [.DocumentAST](#hydrolysis.DocumentAST) : <code>Object</code>
  52 + * [.ElementDescriptor](#hydrolysis.ElementDescriptor) : <code>Object</code>
  53 + * [.FeatureDescriptor](#hydrolysis.FeatureDescriptor) : <code>Object</code>
  54 + * [.BehaviorDescriptor](#hydrolysis.BehaviorDescriptor) : <code>Object</code>
  55 + * [.DocumentDescriptor](#hydrolysis.DocumentDescriptor) : <code>Object</code>
  56 + * [.AnalyzedDocument](#hydrolysis.AnalyzedDocument) : <code>Object</code>
  57 + * [.LoadOptions](#hydrolysis.LoadOptions) : <code>Object</code>
  58 + * [.Resolver](#hydrolysis.Resolver) : <code>Object</code>
  59 +
  60 +<a name="hydrolysis.Analyzer"></a>
  61 +### hydrolysis.Analyzer
  62 +**Kind**: static class of <code>[hydrolysis](#hydrolysis)</code>
  63 +
  64 +* [.Analyzer](#hydrolysis.Analyzer)
  65 + * [new Analyzer(attachAST, [loader])](#new_hydrolysis.Analyzer_new)
  66 + * _instance_
  67 + * [.elements](#hydrolysis.Analyzer#elements) : <code>Array.&lt;ElementDescriptor&gt;</code>
  68 + * [.elementsByTagName](#hydrolysis.Analyzer#elementsByTagName) : <code>Object.&lt;string, ElementDescriptor&gt;</code>
  69 + * [.features](#hydrolysis.Analyzer#features) : <code>Array.&lt;FeatureDescriptor&gt;</code>
  70 + * [.behaviors](#hydrolysis.Analyzer#behaviors) : <code>Array.&lt;BehaviorDescriptor&gt;</code>
  71 + * [.html](#hydrolysis.Analyzer#html) : <code>Object.&lt;string, AnalyzedDocument&gt;</code>
  72 + * [.parsedDocuments](#hydrolysis.Analyzer#parsedDocuments) : <code>Object</code>
  73 + * [._getDependencies(href, [found], [transitive])](#hydrolysis.Analyzer#_getDependencies) โ‡’ <code>Array.&lt;string&gt;</code>
  74 + * [.metadataTree(href)](#hydrolysis.Analyzer#metadataTree) โ‡’ <code>Promise</code>
  75 + * [.nodeWalkDocuments(predicate)](#hydrolysis.Analyzer#nodeWalkDocuments) โ‡’ <code>Object</code>
  76 + * [.annotate()](#hydrolysis.Analyzer#annotate)
  77 + * [.clean()](#hydrolysis.Analyzer#clean)
  78 + * _static_
  79 + * [.analyze(href, [options])](#hydrolysis.Analyzer.analyze) โ‡’ <code>Promise.&lt;Analyzer&gt;</code>
  80 +
  81 +<a name="new_hydrolysis.Analyzer_new"></a>
  82 +#### new Analyzer(attachAST, [loader])
  83 +A database of Polymer metadata defined in HTML
  84 +
  85 +
  86 +| Param | Type | Description |
  87 +| --- | --- | --- |
  88 +| attachAST | <code>boolean</code> | If true, attach a parse5 compliant AST |
  89 +| [loader] | <code>FileLoader</code> | An optional `FileLoader` used to load external resources |
  90 +
  91 +<a name="hydrolysis.Analyzer#elements"></a>
  92 +#### analyzer.elements : <code>Array.&lt;ElementDescriptor&gt;</code>
  93 +A list of all elements the `Analyzer` has metadata for.
  94 +
  95 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  96 +<a name="hydrolysis.Analyzer#elementsByTagName"></a>
  97 +#### analyzer.elementsByTagName : <code>Object.&lt;string, ElementDescriptor&gt;</code>
  98 +A view into `elements`, keyed by tag name.
  99 +
  100 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  101 +<a name="hydrolysis.Analyzer#features"></a>
  102 +#### analyzer.features : <code>Array.&lt;FeatureDescriptor&gt;</code>
  103 +A list of API features added to `Polymer.Base` encountered by the
  104 +analyzer.
  105 +
  106 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  107 +<a name="hydrolysis.Analyzer#behaviors"></a>
  108 +#### analyzer.behaviors : <code>Array.&lt;BehaviorDescriptor&gt;</code>
  109 +The behaviors collected by the analysis pass.
  110 +
  111 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  112 +<a name="hydrolysis.Analyzer#html"></a>
  113 +#### analyzer.html : <code>Object.&lt;string, AnalyzedDocument&gt;</code>
  114 +A map, keyed by absolute path, of Document metadata.
  115 +
  116 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  117 +<a name="hydrolysis.Analyzer#parsedDocuments"></a>
  118 +#### analyzer.parsedDocuments : <code>Object</code>
  119 +A map, keyed by path, of HTML document ASTs.
  120 +
  121 +**Kind**: instance property of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  122 +<a name="hydrolysis.Analyzer#_getDependencies"></a>
  123 +#### analyzer._getDependencies(href, [found], [transitive]) โ‡’ <code>Array.&lt;string&gt;</code>
  124 +List all the html dependencies for the document at `href`.
  125 +
  126 +**Kind**: instance method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  127 +**Returns**: <code>Array.&lt;string&gt;</code> - A list of all the html dependencies.
  128 +
  129 +| Param | Type | Description |
  130 +| --- | --- | --- |
  131 +| href | <code>string</code> | The href to get dependencies for. |
  132 +| [found] | <code>Object.&lt;string, boolean&gt;</code> | An object keyed by URL of the already resolved dependencies. |
  133 +| [transitive] | <code>boolean</code> | Whether to load transitive dependencies. Defaults to true. |
  134 +
  135 +<a name="hydrolysis.Analyzer#metadataTree"></a>
  136 +#### analyzer.metadataTree(href) โ‡’ <code>Promise</code>
  137 +Returns a promise that resolves to a POJO representation of the import
  138 +tree, in a format that maintains the ordering of the HTML imports spec.
  139 +
  140 +**Kind**: instance method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  141 +
  142 +| Param | Type | Description |
  143 +| --- | --- | --- |
  144 +| href | <code>string</code> | the import to get metadata for. |
  145 +
  146 +<a name="hydrolysis.Analyzer#nodeWalkDocuments"></a>
  147 +#### analyzer.nodeWalkDocuments(predicate) โ‡’ <code>Object</code>
  148 +Calls `dom5.nodeWalk` on each document that `Anayzler` has laoded.
  149 +
  150 +**Kind**: instance method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  151 +
  152 +| Param | Type | Description |
  153 +| --- | --- | --- |
  154 +| predicate | <code>Object</code> | A dom5 predicate. |
  155 +
  156 +<a name="hydrolysis.Analyzer#annotate"></a>
  157 +#### analyzer.annotate()
  158 +Annotates all loaded metadata with its documentation.
  159 +
  160 +**Kind**: instance method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  161 +<a name="hydrolysis.Analyzer#clean"></a>
  162 +#### analyzer.clean()
  163 +Removes redundant properties from the collected descriptors.
  164 +
  165 +**Kind**: instance method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  166 +<a name="hydrolysis.Analyzer.analyze"></a>
  167 +#### Analyzer.analyze(href, [options]) โ‡’ <code>Promise.&lt;Analyzer&gt;</code>
  168 +Shorthand for transitively loading and processing all imports beginning at
  169 +`href`.
  170 +
  171 +In order to properly filter paths, `href` _must_ be an absolute URI.
  172 +
  173 +**Kind**: static method of <code>[Analyzer](#hydrolysis.Analyzer)</code>
  174 +**Returns**: <code>Promise.&lt;Analyzer&gt;</code> - A promise that will resolve once `href` and its
  175 + dependencies have been loaded and analyzed.
  176 +
  177 +| Param | Type | Description |
  178 +| --- | --- | --- |
  179 +| href | <code>string</code> | The root import to begin loading from. |
  180 +| [options] | <code>LoadOptions</code> | Any additional options for the load. |
  181 +
  182 +<a name="hydrolysis.FileLoader"></a>
  183 +### hydrolysis.FileLoader
  184 +**Kind**: static class of <code>[hydrolysis](#hydrolysis)</code>
  185 +
  186 +* [.FileLoader](#hydrolysis.FileLoader)
  187 + * [new FileLoader()](#new_hydrolysis.FileLoader_new)
  188 + * [.addResolver(resolver)](#hydrolysis.FileLoader#addResolver)
  189 + * [.request(url)](#hydrolysis.FileLoader#request) โ‡’ <code>Promise.&lt;string&gt;</code>
  190 +
  191 +<a name="new_hydrolysis.FileLoader_new"></a>
  192 +#### new FileLoader()
  193 +A FileLoader lets you resolve URLs with a set of potential resolvers.
  194 +
  195 +<a name="hydrolysis.FileLoader#addResolver"></a>
  196 +#### fileLoader.addResolver(resolver)
  197 +Add an instance of a Resolver class to the list of url resolvers
  198 +
  199 +Ordering of resolvers is most to least recently added
  200 +The first resolver to "accept" the url wins.
  201 +
  202 +**Kind**: instance method of <code>[FileLoader](#hydrolysis.FileLoader)</code>
  203 +
  204 +| Param | Type | Description |
  205 +| --- | --- | --- |
  206 +| resolver | <code>Resolver</code> | The resolver to add. |
  207 +
  208 +<a name="hydrolysis.FileLoader#request"></a>
  209 +#### fileLoader.request(url) โ‡’ <code>Promise.&lt;string&gt;</code>
  210 +Return a promise for an absolute url
  211 +
  212 +Url requests are deduplicated by the loader, returning the same Promise for
  213 +identical urls
  214 +
  215 +**Kind**: instance method of <code>[FileLoader](#hydrolysis.FileLoader)</code>
  216 +**Returns**: <code>Promise.&lt;string&gt;</code> - A promise that resolves to the contents of the URL.
  217 +
  218 +| Param | Type | Description |
  219 +| --- | --- | --- |
  220 +| url | <code>string</code> | The absolute url to request. |
  221 +
  222 +<a name="hydrolysis.FSResolver"></a>
  223 +### hydrolysis.FSResolver
  224 +**Kind**: static class of <code>[hydrolysis](#hydrolysis)</code>
  225 +<a name="new_hydrolysis.FSResolver_new"></a>
  226 +#### new FSResolver(config)
  227 +Resolves requests via the file system.
  228 +
  229 +
  230 +| Param | Type | Description |
  231 +| --- | --- | --- |
  232 +| config | <code>Object</code> | configuration options. |
  233 +| config.host | <code>string</code> | Hostname to match for absolute urls. Matches "/" by default |
  234 +| config.basePath | <code>string</code> | Prefix directory for components in url. Defaults to "/". |
  235 +| config.root | <code>string</code> | Filesystem root to search. Defaults to the current working directory. |
  236 +| config.redirect | <code>string</code> | Where to redirect lookups to siblings. |
  237 +
  238 +<a name="hydrolysis.NoopResolver"></a>
  239 +### hydrolysis.NoopResolver
  240 +**Kind**: static class of <code>[hydrolysis](#hydrolysis)</code>
  241 +
  242 +* [.NoopResolver](#hydrolysis.NoopResolver)
  243 + * [new NoopResolver(config)](#new_hydrolysis.NoopResolver_new)
  244 + * [.accept(uri, deferred)](#hydrolysis.NoopResolver#accept) โ‡’ <code>boolean</code>
  245 +
  246 +<a name="new_hydrolysis.NoopResolver_new"></a>
  247 +#### new NoopResolver(config)
  248 +A resolver that resolves to null any uri matching config.
  249 +
  250 +
  251 +| Param | Type | Description |
  252 +| --- | --- | --- |
  253 +| config | <code>string</code> | The url to `accept`. |
  254 +
  255 +<a name="hydrolysis.NoopResolver#accept"></a>
  256 +#### noopResolver.accept(uri, deferred) โ‡’ <code>boolean</code>
  257 +**Kind**: instance method of <code>[NoopResolver](#hydrolysis.NoopResolver)</code>
  258 +**Returns**: <code>boolean</code> - Whether the URI is handled by this resolver.
  259 +
  260 +| Param | Type | Description |
  261 +| --- | --- | --- |
  262 +| uri | <code>string</code> | The absolute URI being requested. |
  263 +| deferred | <code>Deferred</code> | The deferred promise that should be resolved if this resolver handles the URI. |
  264 +
  265 +<a name="hydrolysis.XHRResolver"></a>
  266 +### hydrolysis.XHRResolver
  267 +**Kind**: static class of <code>[hydrolysis](#hydrolysis)</code>
  268 +<a name="new_hydrolysis.XHRResolver_new"></a>
  269 +#### new XHRResolver(config)
  270 +Construct a resolver that requests resources over XHR.
  271 +
  272 +
  273 +| Param | Type | Description |
  274 +| --- | --- | --- |
  275 +| config | <code>Object</code> | configuration arguments. |
  276 +| config.responseType | <code>string</code> | Type of object to be returned by the XHR. Defaults to 'text', accepts 'document', 'arraybuffer', and 'json'. |
  277 +
  278 +<a name="hydrolysis.DocumentAST"></a>
  279 +### hydrolysis.DocumentAST : <code>Object</code>
  280 +Parse5's representation of a parsed html document
  281 +
  282 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  283 +<a name="hydrolysis.ElementDescriptor"></a>
  284 +### hydrolysis.ElementDescriptor : <code>Object</code>
  285 +The metadata for a single polymer element
  286 +
  287 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  288 +<a name="hydrolysis.FeatureDescriptor"></a>
  289 +### hydrolysis.FeatureDescriptor : <code>Object</code>
  290 +The metadata for a Polymer feature.
  291 +
  292 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  293 +<a name="hydrolysis.BehaviorDescriptor"></a>
  294 +### hydrolysis.BehaviorDescriptor : <code>Object</code>
  295 +The metadata for a Polymer behavior mixin.
  296 +
  297 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  298 +<a name="hydrolysis.DocumentDescriptor"></a>
  299 +### hydrolysis.DocumentDescriptor : <code>Object</code>
  300 +The metadata for all features and elements defined in one document
  301 +
  302 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  303 +**Properties**
  304 +
  305 +| Name | Type | Description |
  306 +| --- | --- | --- |
  307 +| elements | <code>Array.&lt;ElementDescriptor&gt;</code> | The elements from the document |
  308 +| features | <code>Array.&lt;FeatureDescriptor&gt;</code> | The features from the document |
  309 +| behaviors | <code>Array.&lt;FeatureDescriptor&gt;</code> | The behaviors from the document |
  310 +
  311 +<a name="hydrolysis.AnalyzedDocument"></a>
  312 +### hydrolysis.AnalyzedDocument : <code>Object</code>
  313 +The metadata of an entire HTML document, in promises.
  314 +
  315 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  316 +**Properties**
  317 +
  318 +| Name | Type | Description |
  319 +| --- | --- | --- |
  320 +| href | <code>string</code> | The url of the document. |
  321 +| htmlLoaded | <code>Promise.&lt;ParsedImport&gt;</code> | The parsed representation of the doc. Use the `ast` property to get the full `parse5` ast |
  322 +| depsLoaded | <code>Promise.&lt;Array.&lt;string&gt;&gt;</code> | Resolves to the list of this Document's transitive import dependencies |
  323 +| depHrefs | <code>Array.&lt;string&gt;</code> | The direct dependencies of the document. |
  324 +| metadataLoaded | <code>Promise.&lt;DocumentDescriptor&gt;</code> | Resolves to the list of this Document's import dependencies |
  325 +
  326 +<a name="hydrolysis.LoadOptions"></a>
  327 +### hydrolysis.LoadOptions : <code>Object</code>
  328 +Options for `Analyzer.analzye`
  329 +
  330 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  331 +**Properties**
  332 +
  333 +| Name | Type | Description |
  334 +| --- | --- | --- |
  335 +| noAnnotations | <code>boolean</code> | Whether `annotate()` should be skipped. |
  336 +| clean | <code>boolean</code> | Whether the generated descriptors should be cleaned of redundant data. |
  337 +| filter | <code>function</code> | A predicate function that indicates which files should be ignored by the loader. By default all files not located under the dirname of `href` will be ignored. |
  338 +
  339 +<a name="hydrolysis.Resolver"></a>
  340 +### hydrolysis.Resolver : <code>Object</code>
  341 +An object that knows how to resolve resources.
  342 +
  343 +**Kind**: static typedef of <code>[hydrolysis](#hydrolysis)</code>
  344 +**Properties**
  345 +
  346 +| Name | Type | Description |
  347 +| --- | --- | --- |
  348 +| accept | <code>function</code> | Attempt to resolve `deferred` with the contents the specified URL. Returns false if the Resolver is unable to resolve the URL. |
  349 +
  350 +<a name="isSiblingOrAunt"></a>
  351 +## isSiblingOrAunt() โ‡’ <code>boolean</code>
  352 +Returns true if `patha` is a sibling or aunt of `pathb`.
  353 +
  354 +**Kind**: global function
  355 +<a name="redirectSibling"></a>
  356 +## redirectSibling() โ‡’ <code>string</code>
  357 +Change `localPath` from a sibling of `basePath` to be a child of
  358 +`basePath` joined with `redirect`.
  359 +
  360 +**Kind**: global function
... ...
bower_components/hydrolysis/LICENSE 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/LICENSE
  1 +Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
  2 +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  3 +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  4 +Code distributed by Google as part of the polymer project is also
  5 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
0 6 \ No newline at end of file
... ...
bower_components/hydrolysis/README.md 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/README.md
  1 +# hydrolysis
  2 +
  3 +Static anlaysis utilities for polymer.
  4 +
  5 +## Install
  6 +```
  7 +npm install hydrolysis
  8 +```
  9 +
  10 +## Usage
  11 +```js
  12 +var hyd = require('hydrolysis');
  13 +
  14 +hyd.Analyzer.analyze('path-to-polymer-element.html')
  15 + .then(function(analyzer) {
  16 + console.log(analyzer.elementsByTagName['my-element'])
  17 + });
  18 +```
  19 +
  20 +For more detail, see the [API Docs](API.md).
  21 +
  22 +
  23 +## Developing
  24 +You need [wct](https://github.com/Polymer/web-component-tester) to run the tests.
  25 +
  26 +Run a one-off build of the project:
  27 +
  28 +```sh
  29 +npm run build
  30 +```
  31 +
  32 +Or watch the source for changes, and rebuild each time a file is modified:
  33 +
  34 +```sh
  35 +npm run watch
  36 +```
... ...
bower_components/hydrolysis/bower.json 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/bower.json
  1 +{
  2 + "name": "hydrolysis",
  3 + "main": "hydrolysis.js",
  4 + "ignore": [
  5 + "lib/",
  6 + "examples/",
  7 + "demo/",
  8 + "test/",
  9 + ".gitignore",
  10 + "gulpfile.js",
  11 + "package.json"
  12 + ],
  13 + "repository": {
  14 + "type": "git",
  15 + "url": "git://github.com/Polymer/hydrolysis.git"
  16 + },
  17 + "devDependencies": {
  18 + "polymer": "Polymer/polymer#^0.9.0",
  19 + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
  20 + "web-component-tester": "*"
  21 + },
  22 + "version": "1.15.1"
  23 +}
... ...
bower_components/hydrolysis/hydrolysis-analyzer.html 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/hydrolysis-analyzer.html
  1 +<!--
  2 +@license
  3 +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  4 +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  5 +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  6 +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  7 +Code distributed by Google as part of the polymer project is also
  8 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  9 +-->
  10 +<link rel="import" href="../polymer/polymer.html">
  11 +<link rel="import" href="hydrolysis.html">
  12 +
  13 +<script>
  14 +(function() {
  15 +var hydrolysis = require('hydrolysis');
  16 +
  17 + Polymer({
  18 +
  19 + is: 'hydrolysis-analyzer',
  20 +
  21 + properties: {
  22 +
  23 + /**
  24 + * The URL to an import that declares (or transitively imports) the
  25 + * elements that you wish to see analyzed.
  26 + *
  27 + * If the URL is relative, it will be resolved relative to the master
  28 + * document.
  29 + *
  30 + * If you change this value after the `<hydrolysis-analyzer>` has been
  31 + * instantiated, you must call `analyze()`.
  32 + */
  33 + src: {
  34 + type: String,
  35 + },
  36 +
  37 + /**
  38 + * Whether _all_ dependencies should be loaded and analyzed.
  39 + *
  40 + * Turning this on will probably slow down the load process dramatically.
  41 + */
  42 + transitive: {
  43 + type: Boolean,
  44 + },
  45 +
  46 + /**
  47 + * Whether the hydrolysis descriptors should be cleaned of redundant
  48 + * properties.
  49 + */
  50 + clean: {
  51 + type: Boolean,
  52 + },
  53 +
  54 + /** The resultant `Analyzer` object from Hydrolysis. */
  55 + analyzer: {
  56 + type: Object,
  57 + readOnly: true,
  58 + notify: true,
  59 + },
  60 +
  61 + /** Whether the analyzer is loading/analyzing resources. */
  62 + loading: {
  63 + type: Boolean,
  64 + readOnly: true,
  65 + notify: true,
  66 + },
  67 +
  68 + },
  69 +
  70 + ready: function() {
  71 + this.analyze();
  72 + },
  73 +
  74 + /**
  75 + * Begins loading the imports referenced by `src`.
  76 + *
  77 + * If you make changes to this element's configuration, you must call this
  78 + * function to kick off another analysis pass.
  79 + */
  80 + analyze: function() {
  81 + if (!this.src) {
  82 + return;
  83 + }
  84 + // We can implement request cancellation when someone needs it.
  85 + if (this.loading) {
  86 + console.error('Analyzer is already loading a document:', this);
  87 + return;
  88 + }
  89 + this._setLoading(true);
  90 +
  91 + var options = {
  92 + clean: this.clean,
  93 + filter: this.transitive ? function() { return false; } : null,
  94 + attachAst: true,
  95 + };
  96 +
  97 + var baseUri = this.ownerDocument.baseURI;
  98 + var srcUrl = new URL(this.src, baseUri).toString();
  99 + hydrolysis.Analyzer.analyze(srcUrl, options).then(function(analyzer) {
  100 + this._setLoading(false);
  101 + this._setAnalyzer(analyzer);
  102 + }.bind(this))
  103 + .catch(function(error) {
  104 + console.error('Failed to load source at:', this.src, error);
  105 + console.error(error.stack);
  106 + this._setLoading(false);
  107 + this._setAnalyzer(null);
  108 + }.bind(this));
  109 + },
  110 +
  111 + });
  112 +
  113 +})();
  114 +</script>
... ...
bower_components/hydrolysis/hydrolysis.html 0 โ†’ 100755
  1 +++ a/bower_components/hydrolysis/hydrolysis.html
  1 +<!--
  2 +@license
  3 +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  4 +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  5 +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  6 +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  7 +Code distributed by Google as part of the polymer project is also
  8 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  9 +-->
  10 +<script src="hydrolysis.js"></script>
... ...
bower_components/hydrolysis/hydrolysis.js 0 โ†’ 100755
Changes suppressed. Click to show
  1 +++ a/bower_components/hydrolysis/hydrolysis.js
  1 +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2 +(function (global){
  3 +/**
  4 + * @license
  5 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  6 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  7 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  8 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  9 + * Code distributed by Google as part of the polymer project is also
  10 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  11 + */
  12 +// jshint node: true
  13 +'use strict';
  14 +// jshint -W079
  15 +var Promise = global.Promise || require('es6-promise').Promise;
  16 +require("setimmediate");
  17 +// jshint +W079
  18 +
  19 +var dom5 = require('dom5');
  20 +var url = require('url');
  21 +
  22 +var docs = require('./ast-utils/docs');
  23 +var FileLoader = require('./loader/file-loader');
  24 +var importParse = require('./ast-utils/import-parse');
  25 +var jsParse = require('./ast-utils/js-parse');
  26 +var NoopResolver = require('./loader/noop-resolver');
  27 +
  28 +function reduceMetadata(m1, m2) {
  29 + return {
  30 + elements: m1.elements.concat(m2.elements),
  31 + features: m1.features.concat(m2.features),
  32 + behaviors: m1.behaviors.concat(m2.behaviors),
  33 + };
  34 +}
  35 +
  36 +var EMPTY_METADATA = {elements: [], features: [], behaviors: []};
  37 +
  38 +/**
  39 + * Parse5's representation of a parsed html document
  40 + * @typedef {Object} DocumentAST
  41 + * @memberof hydrolysis
  42 + */
  43 +
  44 +/**
  45 + * The metadata for a single polymer element
  46 + * @typedef {Object} ElementDescriptor
  47 + * @memberof hydrolysis
  48 + */
  49 +
  50 +/**
  51 + * The metadata for a Polymer feature.
  52 + * @typedef {Object} FeatureDescriptor
  53 + * @memberof hydrolysis
  54 + */
  55 +
  56 +/**
  57 + * The metadata for a Polymer behavior mixin.
  58 + * @typedef {Object} BehaviorDescriptor
  59 + * @memberof hydrolysis
  60 + */
  61 +
  62 +/**
  63 + * The metadata for all features and elements defined in one document
  64 + * @typedef {Object} DocumentDescriptor
  65 + * @memberof hydrolysis
  66 + * @property {Array<ElementDescriptor>} elements The elements from the document
  67 + * @property {Array<FeatureDescriptor>} features The features from the document
  68 + * @property {Array<FeatureDescriptor>} behaviors The behaviors from the document
  69 + */
  70 +
  71 +/**
  72 + * The metadata of an entire HTML document, in promises.
  73 + * @typedef {Object} AnalyzedDocument
  74 + * @memberof hydrolysis
  75 + * @property {string} href The url of the document.
  76 + * @property {Promise<ParsedImport>} htmlLoaded The parsed representation of
  77 + * the doc. Use the `ast` property to get the full `parse5` ast
  78 + *
  79 + * @property {Promise<Array<string>>} depsLoaded Resolves to the list of this
  80 + * Document's transitive import dependencies
  81 + *
  82 + * @property {Array<string>} depHrefs The direct dependencies of the document.
  83 + *
  84 + * @property {Promise<DocumentDescriptor>} metadataLoaded Resolves to the list of
  85 + * this Document's import dependencies
  86 + */
  87 +
  88 +/**
  89 + * A database of Polymer metadata defined in HTML
  90 + *
  91 + * @constructor
  92 + * @memberOf hydrolysis
  93 + * @param {boolean} attachAST If true, attach a parse5 compliant AST
  94 + * @param {FileLoader=} loader An optional `FileLoader` used to load external
  95 + * resources
  96 + */
  97 +var Analyzer = function Analyzer(attachAST,
  98 + loader) {
  99 + this.loader = loader;
  100 +
  101 + /**
  102 + * A list of all elements the `Analyzer` has metadata for.
  103 + * @member {Array.<ElementDescriptor>}
  104 + */
  105 + this.elements = [];
  106 +
  107 + /**
  108 + * A view into `elements`, keyed by tag name.
  109 + * @member {Object.<string,ElementDescriptor>}
  110 + */
  111 + this.elementsByTagName = {};
  112 +
  113 + /**
  114 + * A list of API features added to `Polymer.Base` encountered by the
  115 + * analyzer.
  116 + * @member {Array<FeatureDescriptor>}
  117 + */
  118 + this.features = [];
  119 +
  120 + /**
  121 + * The behaviors collected by the analysis pass.
  122 + *
  123 + * @member {Array<BehaviorDescriptor>}
  124 + */
  125 + this.behaviors = [];
  126 +
  127 + /**
  128 + * A map, keyed by absolute path, of Document metadata.
  129 + * @member {Object<string,AnalyzedDocument>}
  130 + */
  131 + this.html = {};
  132 +
  133 + this._parsedDocuments = {};
  134 +
  135 + /**
  136 + * A map, keyed by path, of HTML document ASTs.
  137 + * @type {Object}
  138 + */
  139 + this.parsedDocuments = {};
  140 +
  141 + /**
  142 + * A map, keyed by path, of document content.
  143 + * @type {Object}
  144 + */
  145 + this._content = {};
  146 +};
  147 +
  148 +/**
  149 + * Options for `Analyzer.analzye`
  150 + * @typedef {Object} LoadOptions
  151 + * @memberof hydrolysis
  152 + * @property {boolean} noAnnotations Whether `annotate()` should be skipped.
  153 + * @property {boolean} clean Whether the generated descriptors should be cleaned
  154 + * of redundant data.
  155 + * @property {function(string): boolean} filter A predicate function that
  156 + * indicates which files should be ignored by the loader. By default all
  157 + * files not located under the dirname of `href` will be ignored.
  158 + */
  159 +
  160 +/**
  161 + * Shorthand for transitively loading and processing all imports beginning at
  162 + * `href`.
  163 + *
  164 + * In order to properly filter paths, `href` _must_ be an absolute URI.
  165 + *
  166 + * @param {string} href The root import to begin loading from.
  167 + * @param {LoadOptions=} options Any additional options for the load.
  168 + * @return {Promise<Analyzer>} A promise that will resolve once `href` and its
  169 + * dependencies have been loaded and analyzed.
  170 + */
  171 +Analyzer.analyze = function analyze(href, options) {
  172 + options = options || {};
  173 + options.filter = options.filter || _defaultFilter(href);
  174 +
  175 + var loader = new FileLoader();
  176 + var PrimaryResolver = typeof window === 'undefined' ?
  177 + require('./loader/fs-resolver') :
  178 + require('./loader/xhr-resolver');
  179 + loader.addResolver(new PrimaryResolver(options));
  180 + loader.addResolver(new NoopResolver({test: options.filter}));
  181 +
  182 + var analyzer = new this(null, loader);
  183 + return analyzer.metadataTree(href).then(function(root) {
  184 + if (!options.noAnnotations) {
  185 + analyzer.annotate();
  186 + }
  187 + if (options.clean) {
  188 + analyzer.clean();
  189 + }
  190 + return Promise.resolve(analyzer);
  191 + });
  192 +};
  193 +
  194 +/**
  195 + * @private
  196 + * @param {string} href
  197 + * @return {function(string): boolean}
  198 + */
  199 +function _defaultFilter(href) {
  200 + // Everything up to the last `/` or `\`.
  201 + var base = href.match(/^(.*?)[^\/\\]*$/)[1];
  202 + return function(uri) {
  203 + return uri.indexOf(base) !== 0;
  204 + };
  205 +}
  206 +
  207 +Analyzer.prototype.load = function load(href) {
  208 + return this.loader.request(href).then(function(content) {
  209 + return new Promise(function(resolve, reject) {
  210 + setImmediate(function() {
  211 + this._content[href] = content;
  212 + resolve(this._parseHTML(content, href));
  213 + }.bind(this));
  214 + }.bind(this));
  215 + }.bind(this));
  216 +};
  217 +
  218 +/**
  219 + * Returns an `AnalyzedDocument` representing the provided document
  220 + * @private
  221 + * @param {string} htmlImport Raw text of an HTML document
  222 + * @param {string} href The document's URL.
  223 + * @return {AnalyzedDocument} An `AnalyzedDocument`
  224 + */
  225 +Analyzer.prototype._parseHTML = function _parseHTML(htmlImport,
  226 + href) {
  227 + if (href in this.html) {
  228 + return this.html[href];
  229 + }
  230 + var depsLoaded = [];
  231 + var depHrefs = [];
  232 + var metadataLoaded = Promise.resolve(EMPTY_METADATA);
  233 + var parsed;
  234 + try {
  235 + parsed = importParse(htmlImport, href);
  236 + } catch (err) {
  237 + console.error('Error parsing!');
  238 + throw err;
  239 + }
  240 + var htmlLoaded = Promise.resolve(parsed);
  241 + if (parsed.script) {
  242 + metadataLoaded = this._processScripts(parsed.script, href);
  243 + depsLoaded.push(metadataLoaded);
  244 + }
  245 +
  246 + if (this.loader) {
  247 + var baseUri = href;
  248 + if (parsed.base.length > 1) {
  249 + console.error("Only one base tag per document!");
  250 + throw "Multiple base tags in " + href;
  251 + } else if (parsed.base.length == 1) {
  252 + var baseHref = dom5.getAttribute(parsed.base[0], "href");
  253 + if (baseHref) {
  254 + baseHref = baseHref + "/";
  255 + baseUri = url.resolve(baseUri, baseHref);
  256 + }
  257 + }
  258 + parsed.import.forEach(function(link) {
  259 + var linkurl = dom5.getAttribute(link, 'href');
  260 + if (linkurl) {
  261 + var resolvedUrl = url.resolve(baseUri, linkurl);
  262 + depHrefs.push(resolvedUrl);
  263 + depsLoaded.push(this._dependenciesLoadedFor(resolvedUrl, href));
  264 + }
  265 + }.bind(this));
  266 + parsed.style.forEach(function(styleElement) {
  267 + if (polymerExternalStyle(styleElement)) {
  268 + var styleHref = dom5.getAttribute(styleElement, 'href');
  269 + if (href) {
  270 + styleHref = url.resolve(baseUri, styleHref);
  271 + depsLoaded.push(this.loader.request(styleHref).then(function(content){
  272 + this._content[styleHref] = content;
  273 + }.bind(this)));
  274 + }
  275 + }
  276 + }.bind(this));
  277 + }
  278 + depsLoaded = Promise.all(depsLoaded)
  279 + .then(function() {return depHrefs;})
  280 + .catch(function(err) {throw err;});
  281 + this._parsedDocuments[href] = parsed;
  282 + this.parsedDocuments[href] = parsed.ast;
  283 + this.html[href] = {
  284 + href: href,
  285 + htmlLoaded: htmlLoaded,
  286 + metadataLoaded: metadataLoaded,
  287 + depHrefs: depHrefs,
  288 + depsLoaded: depsLoaded
  289 + };
  290 + return this.html[href];
  291 +};
  292 +
  293 +Analyzer.prototype._processScripts = function _processScripts(scripts, href) {
  294 + var scriptPromises = [];
  295 + scripts.forEach(function(script) {
  296 + scriptPromises.push(this._processScript(script, href));
  297 + }.bind(this));
  298 + return Promise.all(scriptPromises).then(function(metadataList) {
  299 + return metadataList.reduce(reduceMetadata, EMPTY_METADATA);
  300 + });
  301 +};
  302 +
  303 +Analyzer.prototype._processScript = function _processScript(script, href) {
  304 + var src = dom5.getAttribute(script, 'src');
  305 + var parsedJs;
  306 + if (!src) {
  307 + try {
  308 + parsedJs = jsParse(script.childNodes[0].value);
  309 + } catch (err) {
  310 + // Figure out the correct line number for the error.
  311 + var line = 0;
  312 + var col = 0;
  313 + if (script.__ownerDocument && script.__ownerDocument == href) {
  314 + line = script.__locationDetail.line - 1;
  315 + col = script.__locationDetail.line - 1;
  316 + }
  317 + line += err.lineNumber;
  318 + col += err.column;
  319 + var message = "Error parsing script in " + href + " at " + line + ":" + col;
  320 + message += "\n" + err.description;
  321 + throw new Error(message);
  322 + }
  323 + if (parsedJs.elements) {
  324 + parsedJs.elements.forEach(function(element) {
  325 + element.scriptElement = script;
  326 + element.contentHref = href;
  327 + this.elements.push(element);
  328 + if (element.is in this.elementsByTagName) {
  329 + console.warn('Ignoring duplicate element definition: ' + element.is);
  330 + } else {
  331 + this.elementsByTagName[element.is] = element;
  332 + }
  333 + }.bind(this));
  334 + }
  335 + if (parsedJs.features) {
  336 + parsedJs.features.forEach(function(feature){
  337 + feature.contentHref = href;
  338 + feature.scriptElement = script;
  339 + });
  340 + this.features = this.features.concat(parsedJs.features);
  341 + }
  342 + if (parsedJs.behaviors) {
  343 + parsedJs.behaviors.forEach(function(behavior){
  344 + behavior.contentHref = href;
  345 + });
  346 + this.behaviors = this.behaviors.concat(parsedJs.behaviors);
  347 + }
  348 + return parsedJs;
  349 + }
  350 + if (this.loader) {
  351 + var resolvedSrc = url.resolve(href, src);
  352 + return this.loader.request(resolvedSrc).then(function(content) {
  353 + this._content[resolvedSrc] = content;
  354 + var resolvedScript = Object.create(script);
  355 + resolvedScript.childNodes = [{value: content}];
  356 + resolvedScript.attrs = resolvedScript.attrs.slice();
  357 + dom5.removeAttribute(resolvedScript, 'src');
  358 + return this._processScript(resolvedScript, resolvedSrc);
  359 + }.bind(this)).catch(function(err) {throw err;});
  360 + } else {
  361 + return Promise.resolve(EMPTY_METADATA);
  362 + }
  363 +};
  364 +
  365 +Analyzer.prototype._dependenciesLoadedFor = function _dependenciesLoadedFor(href, root) {
  366 + var found = {};
  367 + if (root !== undefined) {
  368 + found[root] = true;
  369 + }
  370 + return this._getDependencies(href, found).then(function(deps) {
  371 + var depMetadataLoaded = [];
  372 + var depPromises = deps.map(function(depHref){
  373 + return this.load(depHref).then(function(htmlMonomer) {
  374 + return htmlMonomer.metadataLoaded;
  375 + });
  376 + }.bind(this));
  377 + return Promise.all(depPromises);
  378 + }.bind(this));
  379 +};
  380 +
  381 +/**
  382 + * List all the html dependencies for the document at `href`.
  383 + * @param {string} href The href to get dependencies for.
  384 + * @param {Object.<string,boolean>=} found An object keyed by URL of the
  385 + * already resolved dependencies.
  386 + * @param {boolean=} transitive Whether to load transitive
  387 + * dependencies. Defaults to true.
  388 + * @return {Array.<string>} A list of all the html dependencies.
  389 + */
  390 +Analyzer.prototype._getDependencies = function _getDependencies(href, found, transitive) {
  391 + if (found === undefined) {
  392 + found = {};
  393 + found[href] = true;
  394 + }
  395 + if (transitive === undefined) {
  396 + transitive = true;
  397 + }
  398 + var deps = [];
  399 + return this.load(href).then(function(htmlMonomer) {
  400 + var transitiveDeps = [];
  401 + htmlMonomer.depHrefs.forEach(function(depHref){
  402 + if (found[depHref]) {
  403 + return;
  404 + }
  405 + deps.push(depHref);
  406 + found[depHref] = true;
  407 + if (transitive) {
  408 + transitiveDeps.push(this._getDependencies(depHref, found));
  409 + }
  410 + }.bind(this));
  411 + return Promise.all(transitiveDeps);
  412 + }.bind(this)).then(function(transitiveDeps) {
  413 + var alldeps = transitiveDeps.reduce(function(a, b) {
  414 + return a.concat(b);
  415 + }, []).concat(deps);
  416 + return alldeps;
  417 + });
  418 +};
  419 +
  420 +/**
  421 + * Returns a promise that resolves to a POJO representation of the import
  422 + * tree, in a format that maintains the ordering of the HTML imports spec.
  423 + * @param {string} href the import to get metadata for.
  424 + * @return {Promise}
  425 + */
  426 +Analyzer.prototype.metadataTree = function metadataTree(href) {
  427 + return this.load(href).then(function(monomer){
  428 + var loadedHrefs = {};
  429 + loadedHrefs[href] = true;
  430 + return this._metadataTree(monomer, loadedHrefs);
  431 + }.bind(this));
  432 +};
  433 +
  434 +Analyzer.prototype._metadataTree = function _metadataTree(htmlMonomer,
  435 + loadedHrefs) {
  436 + if (loadedHrefs === undefined) {
  437 + loadedHrefs = {};
  438 + }
  439 + return htmlMonomer.metadataLoaded.then(function(metadata) {
  440 + metadata = {
  441 + elements: metadata.elements,
  442 + features: metadata.features,
  443 + href: htmlMonomer.href
  444 + };
  445 + return htmlMonomer.depsLoaded.then(function(hrefs) {
  446 + var depMetadata = [];
  447 + hrefs.forEach(function(href) {
  448 + var metadataPromise = Promise.resolve(true);
  449 + if (depMetadata.length > 0) {
  450 + metadataPromise = depMetadata[depMetadata.length - 1];
  451 + }
  452 + metadataPromise = metadataPromise.then(function() {
  453 + if (!loadedHrefs[href]) {
  454 + loadedHrefs[href] = true;
  455 + return this._metadataTree(this.html[href], loadedHrefs);
  456 + } else {
  457 + return Promise.resolve({});
  458 + }
  459 + }.bind(this));
  460 + depMetadata.push(metadataPromise);
  461 + }.bind(this));
  462 + return Promise.all(depMetadata).then(function(importMetadata) {
  463 + metadata.imports = importMetadata;
  464 + return htmlMonomer.htmlLoaded.then(function(parsedHtml) {
  465 + metadata.html = parsedHtml;
  466 + if (metadata.elements) {
  467 + metadata.elements.forEach(function(element) {
  468 + attachDomModule(parsedHtml, element);
  469 + });
  470 + }
  471 + return metadata;
  472 + });
  473 + });
  474 + }.bind(this));
  475 + }.bind(this));
  476 +};
  477 +
  478 +function matchingImport(importElement) {
  479 + var matchesTag = dom5.predicates.hasTagName(importElement.tagName);
  480 + var matchesHref = dom5.predicates.hasAttrValue('href', dom5.getAttribute(importElement, 'href'));
  481 + var matchesRel = dom5.predicates.hasAttrValue('rel', dom5.getAttribute(importElement, 'rel'));
  482 + return dom5.predicates.AND(matchesTag, matchesHref, matchesRel);
  483 +}
  484 +
  485 +// TODO(ajo): Refactor out of vulcanize into dom5.
  486 +var polymerExternalStyle = dom5.predicates.AND(
  487 + dom5.predicates.hasTagName('link'),
  488 + dom5.predicates.hasAttrValue('rel', 'import'),
  489 + dom5.predicates.hasAttrValue('type', 'css')
  490 +);
  491 +
  492 +var externalScript = dom5.predicates.AND(
  493 + dom5.predicates.hasTagName('script'),
  494 + dom5.predicates.hasAttr('src')
  495 +);
  496 +
  497 +var isHtmlImportNode = dom5.predicates.AND(
  498 + dom5.predicates.hasTagName('link'),
  499 + dom5.predicates.hasAttrValue('rel', 'import'),
  500 + dom5.predicates.NOT(
  501 + dom5.predicates.hasAttrValue('type', 'css')
  502 + )
  503 +);
  504 +
  505 +Analyzer.prototype._inlineStyles = function _inlineStyles(ast, href) {
  506 + var cssLinks = dom5.queryAll(ast, polymerExternalStyle);
  507 + cssLinks.forEach(function(link) {
  508 + var linkHref = dom5.getAttribute(link, 'href');
  509 + var uri = url.resolve(href, linkHref);
  510 + var content = this._content[uri];
  511 + var style = dom5.constructors.element('style');
  512 + dom5.setTextContent(style, '\n' + content + '\n');
  513 + dom5.replace(link, style);
  514 + }.bind(this));
  515 + return cssLinks.length > 0;
  516 +};
  517 +
  518 +Analyzer.prototype._inlineScripts = function _inlineScripts(ast, href) {
  519 + var scripts = dom5.queryAll(ast, externalScript);
  520 + scripts.forEach(function(script) {
  521 + var scriptHref = dom5.getAttribute(script, 'src');
  522 + var uri = url.resolve(href, scriptHref);
  523 + var content = this._content[uri];
  524 + var inlined = dom5.constructors.element('script');
  525 + dom5.setTextContent(inlined, '\n' + content + '\n');
  526 + dom5.replace(script, inlined);
  527 + }.bind(this));
  528 + return scripts.length > 0;
  529 +};
  530 +
  531 +Analyzer.prototype._inlineImports = function _inlineImports(ast, href, loaded) {
  532 + var imports = dom5.queryAll(ast, isHtmlImportNode);
  533 + imports.forEach(function(htmlImport) {
  534 + var importHref = dom5.getAttribute(htmlImport, 'href');
  535 + var uri = url.resolve(href, importHref);
  536 + if (loaded[uri]) {
  537 + dom5.remove(htmlImport);
  538 + return;
  539 + }
  540 + var content = this.getLoadedAst(uri, loaded);
  541 + dom5.replace(htmlImport, content);
  542 + }.bind(this));
  543 + return imports.length > 0;
  544 +};
  545 +
  546 +/**
  547 + * Returns a promise resolving to a form of the AST with all links replaced
  548 + * with the document they link to. .css and .script files become <style> and
  549 + * <script>, respectively.
  550 + *
  551 + * The elements in the loaded document are unmodified from their original
  552 + * documents.
  553 + *
  554 + * @param {string} href The document to load.
  555 + * @param {Object.<string,boolean>=} loaded An object keyed by already loaded documents.
  556 + * @return {Promise.<DocumentAST>}
  557 + */
  558 +Analyzer.prototype.getLoadedAst = function getLoadedAst(href, loaded) {
  559 + if (!loaded) {
  560 + loaded = {};
  561 + }
  562 + loaded[href] = true;
  563 + var document = this._parsedDocuments[href];
  564 + var analyzedDocument = this.html[href];
  565 + var astCopy = dom5.parse(dom5.serialize(document.ast));
  566 + // Whenever we inline something, reset inlined to true to know that anoather
  567 + // inlining pass is needed;
  568 + this._inlineStyles(astCopy, href);
  569 + this._inlineScripts(astCopy, href);
  570 + this._inlineImports(astCopy, href, loaded);
  571 + return astCopy;
  572 +};
  573 +
  574 +/**
  575 + * Calls `dom5.nodeWalkAll` on each document that `Anayzler` has laoded.
  576 + * @param {Object} predicate A dom5 predicate.
  577 + * @return {Object}
  578 + */
  579 +Analyzer.prototype.nodeWalkDocuments = function nodeWalkDocuments(predicate) {
  580 + for (var href in this._parsedDocuments) {
  581 + var match = dom5.nodeWalk(this._parsedDocuments[href].ast, predicate);
  582 + if (match) {
  583 + return match;
  584 + }
  585 + }
  586 + return null;
  587 +};
  588 +
  589 +/**
  590 + * Calls `dom5.nodeWalkAll` on each document that `Anayzler` has laoded.
  591 + * @param {Object} predicate A dom5 predicate.
  592 + * @return {Object}
  593 + */
  594 +Analyzer.prototype.nodeWalkAllDocuments = function nodeWalkDocuments(predicate) {
  595 + var results = [];
  596 + for (var href in this._parsedDocuments) {
  597 + var newNodes = dom5.nodeWalkAll(this._parsedDocuments[href].ast, predicate);
  598 + results = results.concat(newNodes);
  599 + }
  600 + return results;
  601 +};
  602 +
  603 +/** Annotates all loaded metadata with its documentation. */
  604 +Analyzer.prototype.annotate = function annotate() {
  605 + if (this.features.length > 0) {
  606 + var featureEl = docs.featureElement(this.features);
  607 + this.elements.unshift(featureEl);
  608 + this.elementsByTagName[featureEl.is] = featureEl;
  609 + }
  610 +
  611 + this.elements.forEach(docs.annotateElement);
  612 + this.behaviors.forEach(docs.annotateElement); // Same shape.
  613 +};
  614 +
  615 +function attachDomModule(parsedImport, element) {
  616 + var domModules = parsedImport['dom-module'];
  617 + for (var i = 0, domModule; i < domModules.length; i++) {
  618 + domModule = domModules[i];
  619 + if (dom5.getAttribute(domModule, 'id') === element.is) {
  620 + element.domModule = domModule;
  621 + return;
  622 + }
  623 + }
  624 +}
  625 +
  626 +/** Removes redundant properties from the collected descriptors. */
  627 +Analyzer.prototype.clean = function clean() {
  628 + this.elements.forEach(docs.cleanElement);
  629 +};
  630 +
  631 +module.exports = Analyzer;
  632 +
  633 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  634 +
  635 +},{"./ast-utils/docs":5,"./ast-utils/import-parse":10,"./ast-utils/js-parse":11,"./loader/file-loader":13,"./loader/fs-resolver":14,"./loader/noop-resolver":15,"./loader/xhr-resolver":16,"dom5":38,"es6-promise":60,"setimmediate":74,"url":26}],2:[function(require,module,exports){
  636 +/**
  637 + * @license
  638 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  639 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  640 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  641 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  642 + * Code distributed by Google as part of the polymer project is also
  643 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  644 + */
  645 +// jshint node: true
  646 +'use strict';
  647 +
  648 +var esutil = require('./esutil');
  649 +var astValue = require('./ast-value');
  650 +
  651 +var analyzeProperties = function(node) {
  652 +
  653 + var analyzedProps = [];
  654 +
  655 + if (node.type != 'ObjectExpression') {
  656 + return analyzedProps;
  657 + }
  658 + for (var i = 0; i < node.properties.length; i++) {
  659 + var property = node.properties[i];
  660 + var prop = esutil.toPropertyDescriptor(property);
  661 + prop.published = true;
  662 +
  663 + if (property.value.type == 'ObjectExpression') {
  664 + /**
  665 + * Parse the expression inside a property object block.
  666 + * property: {
  667 + * key: {
  668 + * type: String,
  669 + * notify: true,
  670 + * value: -1,
  671 + * readOnly: true,
  672 + * reflectToAttribute: true
  673 + * }
  674 + * }
  675 + */
  676 + for (var j = 0; j < property.value.properties.length; j++) {
  677 + var propertyArg = property.value.properties[j];
  678 + var propertyKey = esutil.objectKeyToString(propertyArg.key);
  679 +
  680 + switch(propertyKey) {
  681 + case 'type': {
  682 + prop.type = esutil.objectKeyToString(propertyArg.value);
  683 + if (prop.type === undefined) {
  684 + throw {
  685 + message: 'Invalid type in property object.',
  686 + location: propertyArg.loc.start
  687 + };
  688 + }
  689 + }
  690 + break;
  691 + case 'notify': {
  692 + prop.notify = astValue.expressionToValue(propertyArg.value);
  693 + if (prop.notify === undefined)
  694 + prop.notify = astValue.CANT_CONVERT;
  695 + }
  696 + break;
  697 + case 'observer': {
  698 + prop.observer = astValue.expressionToValue(propertyArg.value);
  699 + prop.observerNode = propertyArg.value;
  700 + if (prop.observer === undefined)
  701 + prop.observer = astValue.CANT_CONVERT;
  702 + }
  703 + break;
  704 + case 'readOnly': {
  705 + prop.readOnly = astValue.expressionToValue(propertyArg.value);
  706 + if (prop.readOnly === undefined)
  707 + prop.readOnly = astValue.CANT_CONVERT;
  708 + }
  709 + break;
  710 + case 'reflectToAttribute': {
  711 + prop.reflectToAttribute = astValue.expressionToValue(propertyArg);
  712 + if (prop.reflectToAttribute === undefined)
  713 + prop.reflectToAttribute = astValue.CANT_CONVERT;
  714 + }
  715 + break;
  716 + case 'value': {
  717 + prop.default = astValue.expressionToValue(propertyArg.value);
  718 + if (prop.default === undefined)
  719 + prop.default = astValue.CANT_CONVERT;
  720 + }
  721 + break;
  722 + default:
  723 + break;
  724 + }
  725 + }
  726 + }
  727 +
  728 + if (!prop.type) {
  729 + throw {
  730 + message: 'Unable to determine name for property key.',
  731 + location: node.loc.start
  732 + };
  733 + }
  734 +
  735 + analyzedProps.push(prop);
  736 + }
  737 + return analyzedProps;
  738 +};
  739 +
  740 +
  741 +module.exports = analyzeProperties;
  742 +
  743 +
  744 +},{"./ast-value":3,"./esutil":7}],3:[function(require,module,exports){
  745 +/**
  746 + * @license
  747 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  748 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  749 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  750 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  751 + * Code distributed by Google as part of the polymer project is also
  752 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  753 + */
  754 +// jshint node: true
  755 +'use strict';
  756 +
  757 +// useful tool to visualize AST: http://esprima.org/demo/parse.html
  758 +
  759 +/**
  760 + * converts literal: {"type": "Literal", "value": 5, "raw": "5" }
  761 + * to string
  762 + */
  763 +function literalToValue(literal) {
  764 + return literal.value;
  765 +}
  766 +
  767 +/**
  768 + * converts unary to string
  769 + * unary: { type: 'UnaryExpression', operator: '-', argument: { ... } }
  770 + */
  771 +function unaryToValue(unary) {
  772 + var argValue = expressionToValue(unary.argument);
  773 + if (argValue === undefined)
  774 + return;
  775 + return unary.operator + argValue;
  776 +}
  777 +
  778 +/**
  779 + * converts identifier to its value
  780 + * identifier { "type": "Identifier", "name": "Number }
  781 + */
  782 +function identifierToValue(identifier) {
  783 + return identifier.name;
  784 +}
  785 +
  786 +/**
  787 + * Function is a block statement.
  788 + */
  789 +function functionDeclarationToValue(fn) {
  790 + if (fn.body.type == "BlockStatement")
  791 + return blockStatementToValue(fn.body);
  792 +}
  793 +
  794 +function functionExpressionToValue(fn) {
  795 + if (fn.body.type == "BlockStatement")
  796 + return blockStatementToValue(fn.body);
  797 +}
  798 +/**
  799 + * Block statement: find last return statement, and return its value
  800 + */
  801 +function blockStatementToValue(block) {
  802 + for (var i=block.body.length - 1; i>= 0; i--) {
  803 + if (block.body[i].type === "ReturnStatement")
  804 + return returnStatementToValue(block.body[i]);
  805 + }
  806 +}
  807 +
  808 +/**
  809 + * Evaluates return's argument
  810 + */
  811 +function returnStatementToValue(ret) {
  812 + return expressionToValue(ret.argument);
  813 +}
  814 +
  815 +/**
  816 + * Enclose containing values in []
  817 + */
  818 +function arrayExpressionToValue(arry) {
  819 + var value = '[';
  820 + for (var i=0; i<arry.elements.length; i++) {
  821 + var v = expressionToValue(arry.elements[i]);
  822 + if (v === undefined)
  823 + v = CANT_CONVERT;
  824 + if (i !== 0)
  825 + value += ', ';
  826 + value += v;
  827 + }
  828 + value += ']';
  829 + return value;
  830 +}
  831 +
  832 +/**
  833 + * Make it look like an object
  834 + */
  835 +function objectExpressionToValue(obj) {
  836 + var value = '{';
  837 + for (var i=0; i<obj.properties.length; i++) {
  838 + var k = expressionToValue(obj.properties[i].key);
  839 + var v = expressionToValue(obj.properties[i].value);
  840 + if (v === undefined)
  841 + v = CANT_CONVERT;
  842 + if (i !== 0)
  843 + value += ', ';
  844 + value += '"' + k + '": ' + v;
  845 + }
  846 + value += '}';
  847 + return value;
  848 +}
  849 +
  850 +/**
  851 + * MemberExpression references a variable with name
  852 + */
  853 +function memberExpressionToValue(member) {
  854 + return expressionToValue(member.object) + "." + expressionToValue(member.property);
  855 +}
  856 +
  857 +/**
  858 + * Tries to get a value from expression. Handles Literal, UnaryExpression
  859 + * returns undefined on failure
  860 + * valueExpression example:
  861 + * { type: "Literal",
  862 + */
  863 +function expressionToValue(valueExpression) {
  864 + switch(valueExpression.type) {
  865 + case 'Literal':
  866 + return literalToValue(valueExpression);
  867 + case 'UnaryExpression':
  868 + return unaryToValue(valueExpression);
  869 + case 'Identifier':
  870 + return identifierToValue(valueExpression);
  871 + case 'FunctionDeclaration':
  872 + return functionDeclarationToValue(valueExpression);
  873 + case 'FunctionExpression':
  874 + return functionExpressionToValue(valueExpression);
  875 + case 'ArrayExpression':
  876 + return arrayExpressionToValue(valueExpression);
  877 + case 'ObjectExpression':
  878 + return objectExpressionToValue(valueExpression);
  879 + case 'Identifier':
  880 + return identifierToValue(valueExpression);
  881 + case 'MemberExpression':
  882 + return memberExpressionToValue(valueExpression);
  883 + default:
  884 + return;
  885 + }
  886 +}
  887 +
  888 +var CANT_CONVERT = 'UNKNOWN';
  889 +module.exports = {
  890 + CANT_CONVERT: CANT_CONVERT,
  891 + expressionToValue: expressionToValue
  892 +};
  893 +
  894 +},{}],4:[function(require,module,exports){
  895 +/**
  896 + * @license
  897 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  898 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  899 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  900 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  901 + * Code distributed by Google as part of the polymer project is also
  902 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  903 + */
  904 +// jshint node: true
  905 +'use strict';
  906 +var estraverse = require('estraverse');
  907 +
  908 +var docs = require('./docs');
  909 +var esutil = require('./esutil');
  910 +var jsdoc = require('./jsdoc');
  911 +var analyzeProperties = require('./analyze-properties');
  912 +var astValue = require('./ast-value.js');
  913 +
  914 +module.exports = function behaviorFinder() {
  915 + /** @type {!Array<BehaviorDescriptor>} The behaviors we've found. */
  916 + var behaviors = [];
  917 +
  918 + var currentBehavior = null;
  919 +
  920 + /**
  921 + * special-case properties
  922 + */
  923 + var propertyHandlers = {
  924 + properties: function(node) {
  925 + var props = analyzeProperties(node);
  926 +
  927 + for (var i=0; i < props.length; i++) {
  928 + currentBehavior.properties.push(props[i]);
  929 + }
  930 + }
  931 + };
  932 +
  933 + /**
  934 + * merges behavior with preexisting behavior with the same name.
  935 + * here to support multiple @polymerBehavior tags referring
  936 + * to same behavior. See iron-multi-selectable for example.
  937 + */
  938 + function mergeBehavior(newBehavior) {
  939 + var isBehaviorImpl = function(b) { // filter out BehaviorImpl
  940 + return b.indexOf(newBehavior.is) === -1;
  941 + };
  942 + for (var i=0; i<behaviors.length; i++) {
  943 + if (newBehavior.is !== behaviors[i].is)
  944 + continue;
  945 + // merge desc, longest desc wins
  946 + if (newBehavior.desc) {
  947 + if (behaviors[i].desc) {
  948 + if (newBehavior.desc.length > behaviors[i].desc.length)
  949 + behaviors[i].desc = newBehavior.desc;
  950 + }
  951 + else {
  952 + behaviors[i].desc = newBehavior.desc;
  953 + }
  954 + }
  955 + // merge demos
  956 + behaviors[i].demos = (behaviors[i].demos || []).concat(newBehavior.demos || []);
  957 + // merge events,
  958 + behaviors[i].events = (behaviors[i].events || []).concat(newBehavior.events || []);
  959 + // merge properties
  960 + behaviors[i].properties = (behaviors[i].properties || []).concat(newBehavior.properties || []);
  961 + // merge behaviors
  962 + behaviors[i].behaviors =
  963 + (behaviors[i].behaviors || []).concat(newBehavior.behaviors || [])
  964 + .filter(isBehaviorImpl);
  965 + return behaviors[i];
  966 + }
  967 + return newBehavior;
  968 + }
  969 +
  970 + var visitors = {
  971 +
  972 + /**
  973 + * Look for object declarations with @behavior in the docs.
  974 + */
  975 + enterVariableDeclaration: function(node, parent) {
  976 + if (node.declarations.length !== 1) return; // Ambiguous.
  977 + this._initBehavior(node, function () {
  978 + return esutil.objectKeyToString(node.declarations[0].id);
  979 + });
  980 + },
  981 +
  982 + /**
  983 + * Look for object assignments with @polymerBehavior in the docs.
  984 + */
  985 + enterAssignmentExpression: function(node, parent) {
  986 + this._initBehavior(parent, function () {
  987 + return esutil.objectKeyToString(node.left);
  988 + });
  989 + },
  990 +
  991 + _parseChainedBehaviors: function(node) {
  992 + // if current behavior is part of an array, it gets extended by other behaviors
  993 + // inside the array. Ex:
  994 + // Polymer.IronMultiSelectableBehavior = [ {....}, Polymer.IronSelectableBehavior]
  995 + // We add these to behaviors array
  996 + var expression;
  997 + switch(node.type) {
  998 + case 'ExpressionStatement':
  999 + expression = node.expression.right;
  1000 + break;
  1001 + case 'VariableDeclaration':
  1002 + expression = node.declarations.length > 0 ? node.declarations[0].init : null;
  1003 + break;
  1004 + }
  1005 + var chained = [];
  1006 + if (expression && expression.type === 'ArrayExpression') {
  1007 + for (var i=0; i < expression.elements.length; i++) {
  1008 + if (expression.elements[i].type === 'MemberExpression')
  1009 + chained.push(astValue.expressionToValue(expression.elements[i]));
  1010 + }
  1011 + if (chained.length > 0)
  1012 + currentBehavior.behaviors = chained;
  1013 + }
  1014 + },
  1015 +
  1016 + _initBehavior: function(node, getName) {
  1017 + var comment = esutil.getAttachedComment(node);
  1018 + // Quickly filter down to potential candidates.
  1019 + if (!comment || comment.indexOf('@polymerBehavior') === -1) return;
  1020 +
  1021 +
  1022 + currentBehavior = {
  1023 + type: 'behavior',
  1024 + desc: comment,
  1025 + events: esutil.getEventComments(node).map( function(event) {
  1026 + return { desc: event};
  1027 + })
  1028 + };
  1029 +
  1030 + docs.annotateBehavior(currentBehavior);
  1031 + // Make sure that we actually parsed a behavior tag!
  1032 + if (!jsdoc.hasTag(currentBehavior.jsdoc, 'polymerBehavior')) {
  1033 + currentBehavior = null;
  1034 + return;
  1035 + }
  1036 +
  1037 + var name = jsdoc.getTag(currentBehavior.jsdoc, 'polymerBehavior', 'name');
  1038 + if (!name) {
  1039 + name = getName();
  1040 + }
  1041 + if (!name) {
  1042 + console.warn('Unable to determine name for @polymerBehavior:', comment);
  1043 + }
  1044 + currentBehavior.is = name;
  1045 +
  1046 + this._parseChainedBehaviors(node);
  1047 +
  1048 + currentBehavior = mergeBehavior(currentBehavior);
  1049 + },
  1050 +
  1051 + /**
  1052 + * We assume that the object expression after such an assignment is the
  1053 + * behavior's declaration. Seems to be a decent assumption for now.
  1054 + */
  1055 + enterObjectExpression: function(node, parent) {
  1056 + if (!currentBehavior || currentBehavior.properties) return;
  1057 +
  1058 + currentBehavior.properties = currentBehavior.properties || [];
  1059 + for (var i = 0; i < node.properties.length; i++) {
  1060 + var prop = node.properties[i];
  1061 + var name = esutil.objectKeyToString(prop.key);
  1062 + if (!name) {
  1063 + throw {
  1064 + message: 'Cant determine name for property key.',
  1065 + location: node.loc.start
  1066 + };
  1067 + }
  1068 + if (name in propertyHandlers) {
  1069 + propertyHandlers[name](prop.value);
  1070 + }
  1071 + else {
  1072 + currentBehavior.properties.push(esutil.toPropertyDescriptor(prop));
  1073 + }
  1074 + }
  1075 + behaviors.push(currentBehavior);
  1076 + currentBehavior = null;
  1077 + },
  1078 +
  1079 + };
  1080 +
  1081 + return {visitors: visitors, behaviors: behaviors};
  1082 +};
  1083 +
  1084 +},{"./analyze-properties":2,"./ast-value.js":3,"./docs":5,"./esutil":7,"./jsdoc":12,"estraverse":72}],5:[function(require,module,exports){
  1085 +/**
  1086 + * @license
  1087 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1088 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1089 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1090 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1091 + * Code distributed by Google as part of the polymer project is also
  1092 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1093 + */
  1094 +'use strict';
  1095 +
  1096 +// jshint node:true
  1097 +
  1098 +var jsdoc = require('./jsdoc');
  1099 +
  1100 +var dom5 = require('dom5');
  1101 +
  1102 +/** Properties on element prototypes that are purely configuration. */
  1103 +var ELEMENT_CONFIGURATION = [
  1104 + 'attached',
  1105 + 'attributeChanged',
  1106 + 'configure',
  1107 + 'constructor',
  1108 + 'created',
  1109 + 'detached',
  1110 + 'enableCustomStyleProperties',
  1111 + 'extends',
  1112 + 'hostAttributes',
  1113 + 'is',
  1114 + 'listeners',
  1115 + 'mixins',
  1116 + 'observers',
  1117 + 'properties',
  1118 + 'ready',
  1119 + 'registered'
  1120 +];
  1121 +
  1122 +/** Tags understood by the annotation process, to be removed during `clean`. */
  1123 +var HANDLED_TAGS = [
  1124 + 'param',
  1125 + 'return',
  1126 + 'type',
  1127 +];
  1128 +
  1129 +/**
  1130 + * Annotates Hydrolysis descriptors, processing any `desc` properties as JSDoc.
  1131 + *
  1132 + * You probably want to use a more specialized version of this, such as
  1133 + * `annotateElement`.
  1134 + *
  1135 + * Processed JSDoc values will be made available via the `jsdoc` property on a
  1136 + * descriptor node.
  1137 + *
  1138 + * @param {Object} descriptor The descriptor node to process.
  1139 + * @return {Object} The descriptor that was given.
  1140 + */
  1141 +function annotate(descriptor) {
  1142 + if (!descriptor || descriptor.jsdoc) return descriptor;
  1143 +
  1144 + if (typeof descriptor.desc === 'string') {
  1145 + descriptor.jsdoc = jsdoc.parseJsdoc(descriptor.desc);
  1146 + // We want to present the normalized form of a descriptor.
  1147 + descriptor.jsdoc.orig = descriptor.desc;
  1148 + descriptor.desc = descriptor.jsdoc.description;
  1149 + }
  1150 +
  1151 + return descriptor;
  1152 +}
  1153 +
  1154 +/**
  1155 + * Annotates @event, @hero, & @demo tags
  1156 + */
  1157 +function annotateElementHeader(descriptor) {
  1158 + if (descriptor.events) {
  1159 + descriptor.events.forEach(function(event) {
  1160 + _annotateEvent(event);
  1161 + });
  1162 + descriptor.events.sort( function(a,b) {
  1163 + return a.name.localeCompare(b.name);
  1164 + });
  1165 + }
  1166 + descriptor.demos = [];
  1167 + if (descriptor.jsdoc && descriptor.jsdoc.tags) {
  1168 + descriptor.jsdoc.tags.forEach( function(tag) {
  1169 + switch(tag.tag) {
  1170 + case 'hero':
  1171 + descriptor.hero = tag.name || 'hero.png';
  1172 + break;
  1173 + case 'demo':
  1174 + descriptor.demos.push({
  1175 + desc: tag.description || 'demo',
  1176 + path: tag.name || 'demo/index.html'
  1177 + });
  1178 + }
  1179 + });
  1180 + }
  1181 +}
  1182 +
  1183 +/**
  1184 + * Annotates documentation found within a Hydrolysis element descriptor. Also
  1185 + * supports behaviors.
  1186 + *
  1187 + * If the element was processed via `hydrolize`, the element's documentation
  1188 + * will also be extracted via its <dom-module>.
  1189 + *
  1190 + * @param {Object} descriptor The element descriptor.
  1191 + * @return {Object} The descriptor that was given.
  1192 + */
  1193 +function annotateElement(descriptor) {
  1194 + if (!descriptor.desc && descriptor.type === 'element') {
  1195 + descriptor.desc = _findElementDocs(descriptor.is,
  1196 + descriptor.domModule,
  1197 + descriptor.scriptElement);
  1198 + }
  1199 + annotate(descriptor);
  1200 +
  1201 + // The `<dom-module>` is too low level for most needs, and it is _not_
  1202 + // serializable. So we drop it now that we've extracted all the useful bits
  1203 + // from it.
  1204 + delete descriptor.domModule;
  1205 +
  1206 + // Descriptors that should have their `desc` properties parsed as JSDoc.
  1207 + descriptor.properties.forEach(function(property) {
  1208 + // Feature properties are special, configuration is really just a matter of
  1209 + // inheritance...
  1210 + annotateProperty(property, descriptor.abstract);
  1211 + });
  1212 +
  1213 + // It may seem like overkill to always sort, but we have an assumption that
  1214 + // these properties are typically being consumed by user-visible tooling.
  1215 + // As such, it's good to have consistent output/ordering to aid the user.
  1216 + descriptor.properties.sort(function(a, b) {
  1217 + // Private properties are always last.
  1218 + if (a.private && !b.private) {
  1219 + return 1;
  1220 + } else if (!a.private && b.private) {
  1221 + return -1;
  1222 + // Otherwise, we're just sorting alphabetically.
  1223 + } else {
  1224 + return a.name.localeCompare(b.name);
  1225 + }
  1226 + });
  1227 +
  1228 + annotateElementHeader(descriptor);
  1229 +
  1230 + return descriptor;
  1231 +}
  1232 +
  1233 +/**
  1234 + * Annotates behavior descriptor.
  1235 + * @param {Object} descriptor behavior descriptor
  1236 + * @return {Object} descriptor passed in as param
  1237 + */
  1238 +function annotateBehavior(descriptor) {
  1239 + annotate(descriptor);
  1240 +
  1241 + annotateElementHeader(descriptor);
  1242 +
  1243 + return descriptor;
  1244 +}
  1245 +
  1246 +/**
  1247 + * Annotates event documentation
  1248 + */
  1249 +function _annotateEvent(descriptor) {
  1250 + annotate(descriptor);
  1251 + // process @event
  1252 + var eventTag = jsdoc.getTag(descriptor.jsdoc, 'event');
  1253 + descriptor.name = eventTag ? eventTag.description : "N/A";
  1254 +
  1255 + // process @params
  1256 + descriptor.params = (descriptor.jsdoc.tags || [])
  1257 + .filter( function(tag) {
  1258 + return tag.tag === 'param';
  1259 + })
  1260 + .map( function(tag) {
  1261 + return {
  1262 + type: tag.type || "N/A",
  1263 + desc: tag.description,
  1264 + name: tag.name || "N/A"
  1265 + };
  1266 + });
  1267 + // process @params
  1268 + return descriptor;
  1269 +}
  1270 +
  1271 +/**
  1272 + * Annotates documentation found about a Hydrolysis property descriptor.
  1273 + *
  1274 + * @param {Object} descriptor The property descriptor.
  1275 + * @param {boolean} ignoreConfiguration If true, `configuration` is not set.
  1276 + * @return {Object} The descriptior that was given.
  1277 + */
  1278 +function annotateProperty(descriptor, ignoreConfiguration) {
  1279 + annotate(descriptor);
  1280 + if (descriptor.name[0] === '_' || jsdoc.hasTag(descriptor.jsdoc, 'private')) {
  1281 + descriptor.private = true;
  1282 + }
  1283 +
  1284 + if (!ignoreConfiguration && ELEMENT_CONFIGURATION.indexOf(descriptor.name) !== -1) {
  1285 + descriptor.private = true;
  1286 + descriptor.configuration = true;
  1287 + }
  1288 +
  1289 + // @type JSDoc wins
  1290 + descriptor.type = jsdoc.getTag(descriptor.jsdoc, 'type', 'type') || descriptor.type;
  1291 +
  1292 + if (descriptor.type.match(/^function/i)) {
  1293 + _annotateFunctionProperty(descriptor);
  1294 + }
  1295 +
  1296 + // @default JSDoc wins
  1297 + var defaultTag = jsdoc.getTag(descriptor.jsdoc, 'default');
  1298 + if (defaultTag !== null) {
  1299 + descriptor.default = (defaultTag.name || '') + (defaultTag.description || '');
  1300 + }
  1301 +
  1302 + return descriptor;
  1303 +}
  1304 +
  1305 +/** @param {Object} descriptor */
  1306 +function _annotateFunctionProperty(descriptor) {
  1307 + descriptor.function = true;
  1308 +
  1309 + var returnTag = jsdoc.getTag(descriptor.jsdoc, 'return');
  1310 + if (returnTag) {
  1311 + descriptor.return = {
  1312 + type: returnTag.type,
  1313 + desc: returnTag.description,
  1314 + };
  1315 + }
  1316 +
  1317 + var paramsByName = {};
  1318 + (descriptor.params || []).forEach(function(param) {
  1319 + paramsByName[param.name] = param;
  1320 + });
  1321 + (descriptor.jsdoc && descriptor.jsdoc.tags || []).forEach(function(tag) {
  1322 + if (tag.tag !== 'param') return;
  1323 + var param = paramsByName[tag.name];
  1324 + if (!param) {
  1325 + return;
  1326 + }
  1327 +
  1328 + param.type = tag.type || param.type;
  1329 + param.desc = tag.description;
  1330 + });
  1331 +}
  1332 +
  1333 +/**
  1334 + * Converts raw features into an abstract `Polymer.Base` element.
  1335 + *
  1336 + * Note that docs on this element _are not processed_. You must call
  1337 + * `annotateElement` on it yourself if you wish that.
  1338 + *
  1339 + * @param {Array<FeatureDescriptor>} features
  1340 + * @return {ElementDescriptor}
  1341 + */
  1342 +function featureElement(features) {
  1343 + var properties = features.reduce(function(result, feature) {
  1344 + return result.concat(feature.properties);
  1345 + }, []);
  1346 +
  1347 + return {
  1348 + type: 'element',
  1349 + is: 'Polymer.Base',
  1350 + abstract: true,
  1351 + properties: properties,
  1352 + desc: '`Polymer.Base` acts as a base prototype for all Polymer ' +
  1353 + 'elements. It is composed via various calls to ' +
  1354 + '`Polymer.Base._addFeature()`.\n' +
  1355 + '\n' +
  1356 + 'The properties reflected here are the combined view of all ' +
  1357 + 'features found in this library. There may be more properties ' +
  1358 + 'added via other libraries, as well.',
  1359 + };
  1360 +}
  1361 +
  1362 +/**
  1363 + * Cleans redundant properties from a descriptor, assuming that you have already
  1364 + * called `annotate`.
  1365 + *
  1366 + * @param {Object} descriptor
  1367 + */
  1368 +function clean(descriptor) {
  1369 + if (!descriptor.jsdoc) return;
  1370 + // The doctext was written to `descriptor.desc`
  1371 + delete descriptor.jsdoc.description;
  1372 + delete descriptor.jsdoc.orig;
  1373 +
  1374 + var cleanTags = [];
  1375 + (descriptor.jsdoc.tags || []).forEach(function(tag) {
  1376 + // Drop any tags we've consumed.
  1377 + if (HANDLED_TAGS.indexOf(tag.tag) !== -1) return;
  1378 + cleanTags.push(tag);
  1379 + });
  1380 +
  1381 + if (cleanTags.length === 0) {
  1382 + // No tags? no docs left!
  1383 + delete descriptor.jsdoc;
  1384 + } else {
  1385 + descriptor.jsdoc.tags = cleanTags;
  1386 + }
  1387 +}
  1388 +
  1389 +/**
  1390 + * Cleans redundant properties from an element, assuming that you have already
  1391 + * called `annotateElement`.
  1392 + *
  1393 + * @param {ElementDescriptor|BehaviorDescriptor} element
  1394 + */
  1395 +function cleanElement(element) {
  1396 + clean(element);
  1397 + element.properties.forEach(cleanProperty);
  1398 +}
  1399 +
  1400 +/**
  1401 + * Cleans redundant properties from a property, assuming that you have already
  1402 + * called `annotateProperty`.
  1403 + *
  1404 + * @param {PropertyDescriptor} property
  1405 + */
  1406 +function cleanProperty(property) {
  1407 + clean(property);
  1408 +}
  1409 +
  1410 +/**
  1411 + * @param {string} elementId
  1412 + * @param {DocumentAST} domModule
  1413 + * @param {DocumentAST} scriptElement The script that the element was defined in.
  1414 + */
  1415 +function _findElementDocs(elementId, domModule, scriptElement) {
  1416 + // Note that we concatenate docs from all sources if we find them.
  1417 + // element can be defined in:
  1418 + // html comment right before dom-module
  1419 + // html commnet right before script defining the module, if dom-module is empty
  1420 +
  1421 + var found = [];
  1422 +
  1423 + // Do we have a HTML comment on the `<dom-module>` or `<script>`?
  1424 + //
  1425 + // Confusingly, with our current style, the comment will be attached to
  1426 + // `<head>`, rather than being a sibling to the `<dom-module>`
  1427 + var searchRoot = domModule || scriptElement;
  1428 + var parents = dom5.nodeWalkAllPrior(searchRoot, dom5.isCommentNode);
  1429 + var comment = parents.length > 0 ? parents[0] : null;
  1430 + if (comment && comment.data) {
  1431 + found.push(comment.data);
  1432 + }
  1433 + if (found.length === 0) return null;
  1434 + return found
  1435 + .filter(function(comment) {
  1436 + // skip @license comments
  1437 + if (comment && comment.indexOf('@license' === -1)) {
  1438 + return true;
  1439 + }
  1440 + else {
  1441 + return false;
  1442 + }
  1443 + })
  1444 + .map(jsdoc.unindent).join('\n');
  1445 +}
  1446 +
  1447 +function _findLastChildNamed(name, parent) {
  1448 + var children = parent.childNodes;
  1449 + for (var i = children.length - 1, child; i >= 0; i--) {
  1450 + child = children[i];
  1451 + if (child.nodeName === name) return child;
  1452 + }
  1453 + return null;
  1454 +}
  1455 +
  1456 +// TODO(nevir): parse5-utils!
  1457 +function _getNodeAttribute(node, name) {
  1458 + for (var i = 0, attr; i < node.attrs.length; i++) {
  1459 + attr = node.attrs[i];
  1460 + if (attr.name === name) {
  1461 + return attr.value;
  1462 + }
  1463 + }
  1464 +}
  1465 +
  1466 +module.exports = {
  1467 + annotate: annotate,
  1468 + annotateElement: annotateElement,
  1469 + annotateBehavior: annotateBehavior,
  1470 + clean: clean,
  1471 + cleanElement: cleanElement,
  1472 + featureElement: featureElement,
  1473 +};
  1474 +
  1475 +},{"./jsdoc":12,"dom5":38}],6:[function(require,module,exports){
  1476 +/**
  1477 + * @license
  1478 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1479 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1480 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1481 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1482 + * Code distributed by Google as part of the polymer project is also
  1483 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1484 + */
  1485 +// jshint node: true
  1486 +'use strict';
  1487 +var estraverse = require('estraverse');
  1488 +
  1489 +var esutil = require('./esutil');
  1490 +var findAlias = require('./find-alias');
  1491 +var analyzeProperties = require('./analyze-properties');
  1492 +var astValue = require('./ast-value');
  1493 +
  1494 +var elementFinder = function elementFinder() {
  1495 + /**
  1496 + * The list of elements exported by each traversed script.
  1497 + */
  1498 + var elements = [];
  1499 +
  1500 + /**
  1501 + * The element being built during a traversal;
  1502 + */
  1503 + var element;
  1504 +
  1505 + /**
  1506 + * a set of special case properties. these should only be called
  1507 + * when we know we're inside an element definition.
  1508 + * @type {Object}
  1509 + */
  1510 + var propertyHandlers = {
  1511 + is: function(node) {
  1512 + if (node.type == 'Literal') {
  1513 + element.is = node.value;
  1514 + }
  1515 + },
  1516 + properties: function(node) {
  1517 +
  1518 + var props = analyzeProperties(node);
  1519 +
  1520 + for (var i=0; i<props.length; i++) {
  1521 + element.properties.push(props[i]);
  1522 + }
  1523 + },
  1524 + behaviors: function(node) {
  1525 + if (node.type != 'ArrayExpression') {
  1526 + return;
  1527 + }
  1528 + element.behaviors = [];
  1529 +
  1530 + for (var i=0; i<node.elements.length; i++) {
  1531 + var v = astValue.expressionToValue(node.elements[i]);
  1532 + if (v === undefined)
  1533 + v = astValue.CANT_CONVERT;
  1534 + element.behaviors.push(v);
  1535 + }
  1536 + }
  1537 + };
  1538 +
  1539 + var visitors = {
  1540 + enterCallExpression: function enterCallExpression(node, parent) {
  1541 + var callee = node.callee;
  1542 + if (callee.type == 'Identifier') {
  1543 +
  1544 + if (callee.name == 'Polymer') {
  1545 + element = {
  1546 + type: 'element',
  1547 + desc: esutil.getAttachedComment(parent),
  1548 + events: esutil.getEventComments(parent).map( function(event) {
  1549 + return {desc: event};
  1550 + })
  1551 + };
  1552 + }
  1553 + }
  1554 + },
  1555 + leaveCallExpression: function leaveCallExpression(node, parent) {
  1556 + var callee = node.callee;
  1557 + if (callee.type == 'Identifier') {
  1558 + if (callee.name == 'Polymer') {
  1559 + if (element) {
  1560 + elements.push(element);
  1561 + element = undefined;
  1562 + }
  1563 + }
  1564 + }
  1565 + },
  1566 + enterObjectExpression: function enterObjectExpression(node, parent) {
  1567 + if (element && !element.properties) {
  1568 + element.properties = [];
  1569 + for (var i = 0; i < node.properties.length; i++) {
  1570 + var prop = node.properties[i];
  1571 + var name = esutil.objectKeyToString(prop.key);
  1572 + if (!name) {
  1573 + throw {
  1574 + message: 'Cant determine name for property key.',
  1575 + location: node.loc.start
  1576 + };
  1577 + }
  1578 +
  1579 + if (name in propertyHandlers) {
  1580 + propertyHandlers[name](prop.value);
  1581 + continue;
  1582 + }
  1583 + element.properties.push(esutil.toPropertyDescriptor(prop));
  1584 + }
  1585 + return estraverse.VisitorOption.Skip;
  1586 + }
  1587 + }
  1588 + };
  1589 + return {visitors: visitors, elements: elements};
  1590 +};
  1591 +
  1592 +module.exports = elementFinder;
  1593 +
  1594 +},{"./analyze-properties":2,"./ast-value":3,"./esutil":7,"./find-alias":9,"estraverse":72}],7:[function(require,module,exports){
  1595 +/**
  1596 + * @license
  1597 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1598 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1599 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1600 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1601 + * Code distributed by Google as part of the polymer project is also
  1602 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1603 + */
  1604 +// jshint node: true
  1605 +'use strict';
  1606 +var estraverse = require("estraverse");
  1607 +
  1608 +/**
  1609 + * Returns whether an Espree node matches a particular object path.
  1610 + *
  1611 + * e.g. you have a MemberExpression node, and want to see whether it represents
  1612 + * `Foo.Bar.Baz`:
  1613 + *
  1614 + * matchesCallExpression(node, ['Foo', 'Bar', 'Baz'])
  1615 + *
  1616 + * @param {Node} expression The Espree node to match against.
  1617 + * @param {Array<string>} path The path to look for.
  1618 + */
  1619 +function matchesCallExpression(expression, path) {
  1620 + if (!expression.property || !expression.object) return;
  1621 + console.assert(path.length >= 2);
  1622 +
  1623 + // Unravel backwards, make sure properties match each step of the way.
  1624 + if (expression.property.name !== path[path.length - 1]) return false;
  1625 + // We've got ourselves a final member expression.
  1626 + if (path.length == 2 && expression.object.type === 'Identifier') {
  1627 + return expression.object.name === path[0];
  1628 + }
  1629 + // Nested expressions.
  1630 + if (path.length > 2 && expression.object.type == 'MemberExpression') {
  1631 + return matchesCallExpression(expression.object, path.slice(0, path.length - 1));
  1632 + }
  1633 +
  1634 + return false;
  1635 +}
  1636 +
  1637 +/**
  1638 + * @param {Node} key The node representing an object key or expression.
  1639 + * @return {string} The name of that key.
  1640 + */
  1641 +function objectKeyToString(key) {
  1642 + if (key.type == 'Identifier') {
  1643 + return key.name;
  1644 + }
  1645 + if (key.type == 'Literal') {
  1646 + return key.value;
  1647 + }
  1648 + if (key.type == 'MemberExpression') {
  1649 + return objectKeyToString(key.object) + '.' + objectKeyToString(key.property);
  1650 + }
  1651 +}
  1652 +
  1653 +var CLOSURE_CONSTRUCTOR_MAP = {
  1654 + 'Boolean': 'boolean',
  1655 + 'Number': 'number',
  1656 + 'String': 'string',
  1657 +};
  1658 +
  1659 +/**
  1660 + * AST expression -> Closure type.
  1661 + *
  1662 + * Accepts literal values, and native constructors.
  1663 + *
  1664 + * @param {Node} node An Espree expression node.
  1665 + * @return {string} The type of that expression, in Closure terms.
  1666 + */
  1667 +function closureType(node) {
  1668 + if (node.type.match(/Expression$/)) {
  1669 + return node.type.substr(0, node.type.length - 10);
  1670 + } else if (node.type === 'Literal') {
  1671 + return typeof node.value;
  1672 + } else if (node.type === 'Identifier') {
  1673 + return CLOSURE_CONSTRUCTOR_MAP[node.name] || node.name;
  1674 + } else {
  1675 + throw {
  1676 + message: 'Unknown Closure type for node: ' + node.type,
  1677 + location: node.loc.start,
  1678 + };
  1679 + }
  1680 +}
  1681 +
  1682 +/**
  1683 + * @param {Node} node
  1684 + * @return {?string}
  1685 + */
  1686 +function getAttachedComment(node) {
  1687 + var comments = getLeadingComments(node) || getLeadingComments(node.key);
  1688 + if (!comments) {
  1689 + return;
  1690 + }
  1691 + return comments[comments.length - 1];
  1692 +}
  1693 +
  1694 +/**
  1695 + * Returns all comments from a tree defined with @event.
  1696 + * @param {Node} node [description]
  1697 + * @return {[type]} [description]
  1698 + */
  1699 +function getEventComments(node) {
  1700 + var eventComments = [];
  1701 + estraverse.traverse(node, {
  1702 + enter: function (node) {
  1703 + var comments = (node.leadingComments || []).concat(node.trailingComments || [])
  1704 + .map( function(commentAST) {
  1705 + return commentAST.value;
  1706 + })
  1707 + .filter( function(comment) {
  1708 + return comment.indexOf("@event") != -1;
  1709 + });
  1710 + eventComments = eventComments.concat(comments);
  1711 + }
  1712 + });
  1713 + // dedup
  1714 + return eventComments.filter( function(el, index, array) {
  1715 + return array.indexOf(el) === index;
  1716 + });
  1717 +}
  1718 +
  1719 +/**
  1720 + * @param {Node} node
  1721 + * @param
  1722 + * @return {Array.<string>}
  1723 + */
  1724 +function getLeadingComments(node) {
  1725 + if (!node) {
  1726 + return;
  1727 + }
  1728 + var comments = node.leadingComments;
  1729 + if (!comments || comments.length === 0) return;
  1730 + return comments.map(function(comment) {
  1731 + return comment.value;
  1732 + });
  1733 +}
  1734 +
  1735 +/**
  1736 + * Converts a parse5 Property AST node into its Hydrolysis representation.
  1737 + *
  1738 + * @param {Node} node
  1739 + * @return {PropertyDescriptor}
  1740 + */
  1741 +function toPropertyDescriptor(node) {
  1742 + var result = {
  1743 + name: objectKeyToString(node.key),
  1744 + type: closureType(node.value),
  1745 + desc: getAttachedComment(node),
  1746 + javascriptNode: node
  1747 + };
  1748 +
  1749 + if (node.value.type === 'FunctionExpression') {
  1750 + result.params = (node.value.params || []).map(function(param) {
  1751 + return {name: param.name};
  1752 + });
  1753 + }
  1754 +
  1755 + return result;
  1756 +}
  1757 +
  1758 +module.exports = {
  1759 + closureType: closureType,
  1760 + getAttachedComment: getAttachedComment,
  1761 + getEventComments: getEventComments,
  1762 + matchesCallExpression: matchesCallExpression,
  1763 + objectKeyToString: objectKeyToString,
  1764 + toPropertyDescriptor: toPropertyDescriptor,
  1765 +};
  1766 +
  1767 +},{"estraverse":72}],8:[function(require,module,exports){
  1768 +/**
  1769 + * @license
  1770 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1771 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1772 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1773 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1774 + * Code distributed by Google as part of the polymer project is also
  1775 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1776 + */
  1777 +// jshint node: true
  1778 +'use strict';
  1779 +var estraverse = require('estraverse');
  1780 +
  1781 +var esutil = require('./esutil');
  1782 +
  1783 +var numFeatures = 0;
  1784 +
  1785 +module.exports = function featureFinder() {
  1786 + /** @type {!Array<FeatureDescriptor>} The features we've found. */
  1787 + var features = [];
  1788 +
  1789 + var visitors = {
  1790 +
  1791 + enterCallExpression: function enterCallExpression(node, parent) {
  1792 + if (!esutil.matchesCallExpression(node.callee, ['Polymer', 'Base', '_addFeature'])) {
  1793 + return;
  1794 + }
  1795 + /** @type {!FeatureDescriptor} */
  1796 + var feature = {};
  1797 + this._extractDesc(feature, node, parent);
  1798 + this._extractProperties(feature, node, parent);
  1799 +
  1800 + features.push(feature);
  1801 + },
  1802 +
  1803 + _extractDesc: function _extractDesc(feature, node, parent) {
  1804 + feature.desc = esutil.getAttachedComment(parent);
  1805 + },
  1806 +
  1807 + _extractProperties: function _extractProperties(feature, node, parent) {
  1808 + var featureNode = node.arguments[0];
  1809 + if (featureNode.type !== 'ObjectExpression') {
  1810 + console.warn(
  1811 + 'Expected first argument to Polymer.Base._addFeature to be an object.',
  1812 + 'Got', featureNode.type, 'instead.');
  1813 + return;
  1814 + }
  1815 + if (!featureNode.properties) return;
  1816 +
  1817 + feature.properties = featureNode.properties.map(esutil.toPropertyDescriptor);
  1818 + },
  1819 +
  1820 + };
  1821 +
  1822 + return {visitors: visitors, features: features};
  1823 +};
  1824 +
  1825 +},{"./esutil":7,"estraverse":72}],9:[function(require,module,exports){
  1826 +/**
  1827 + * @license
  1828 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1829 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1830 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1831 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1832 + * Code distributed by Google as part of the polymer project is also
  1833 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1834 + */
  1835 +// jshint node: true
  1836 +'use strict';
  1837 +var findAlias = function findAlias(names, aliases, name) {
  1838 + if (!names) {
  1839 + return null;
  1840 + }
  1841 + return aliases[names.indexOf(name)];
  1842 +};
  1843 +
  1844 +module.exports = findAlias;
  1845 +
  1846 +},{}],10:[function(require,module,exports){
  1847 +/**
  1848 + * @license
  1849 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1850 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1851 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1852 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1853 + * Code distributed by Google as part of the polymer project is also
  1854 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1855 + */
  1856 +// jshint node: true
  1857 +'use strict';
  1858 +var dom5 = require('dom5');
  1859 +
  1860 +var p = dom5.predicates;
  1861 +
  1862 +var isHtmlImportNode = p.AND(
  1863 + p.hasTagName('link'),
  1864 + p.hasAttrValue('rel', 'import'),
  1865 + p.NOT(
  1866 + p.hasAttrValue('type', 'css')
  1867 + )
  1868 +);
  1869 +
  1870 +var isStyleNode = p.OR(
  1871 + // inline style
  1872 + p.hasTagName('style'),
  1873 + // external stylesheet
  1874 + p.AND(
  1875 + p.hasTagName('link'),
  1876 + p.hasAttrValue('rel', 'stylesheet')
  1877 + ),
  1878 + // polymer specific external stylesheet
  1879 + p.AND(
  1880 + p.hasTagName('link'),
  1881 + p.hasAttrValue('rel', 'import'),
  1882 + p.hasAttrValue('type', 'css')
  1883 + )
  1884 +);
  1885 +
  1886 +function addNode(node, registry) {
  1887 + if (isHtmlImportNode(node)) {
  1888 + registry.import.push(node);
  1889 + } else if (isStyleNode(node)) {
  1890 + registry.style.push(node);
  1891 + } else if (registry.hasOwnProperty(node.tagName)) {
  1892 + registry[node.tagName].push(node);
  1893 + }
  1894 +}
  1895 +
  1896 +function getLineAndColumn(string, charNumber) {
  1897 + if (charNumber > string.length) {
  1898 + return undefined;
  1899 + }
  1900 + // TODO(ajo): Caching the line lengths of each document could be much faster.
  1901 + var sliced = string.slice(0,charNumber+1);
  1902 + var split = sliced.split('\n');
  1903 + var line = split.length;
  1904 + var column = split[split.length - 1].length;
  1905 + return {line: line, column: column};
  1906 +}
  1907 +
  1908 +/**
  1909 +* Parse5's representation of a parsed html document.
  1910 +* @typedef {Object} DocumentAST
  1911 +*/
  1912 +
  1913 +/**
  1914 +* The ASTs of the HTML elements needed to represent Polymer elements.
  1915 +* @typedef {Object} ParsedImport
  1916 +* @property {Array<DocumentAST>} template The entry points to the AST at each outermost template tag.
  1917 +* @property {Array<DocumentAST>} script The entry points to the AST at each script tag not inside a template.
  1918 +* @property {Array<DocumentAST>} style The entry points to the AST at style tag outside a template.
  1919 +* @property {Array<DocumentAST>} dom-module The entry points to the AST at each outermost dom-module element.
  1920 +* @property {DocumentAST} ast The full parse5 ast for the document.
  1921 +*/
  1922 +
  1923 +/**
  1924 +* Parse html into ASTs.
  1925 +* @param {string} htmlString A utf8, html5 document containing polymer element or module definitons.
  1926 +* @param {string} href The path of the document.
  1927 +* @return {ParsedImport}
  1928 +*/
  1929 +var importParse = function importParse(htmlString, href) {
  1930 + var doc;
  1931 + try {
  1932 + doc = dom5.parse(htmlString, {locationInfo: true});
  1933 + } catch (err) {
  1934 + console.log(err);
  1935 + return null;
  1936 + }
  1937 +
  1938 + // Add line/column information
  1939 + dom5.treeMap(doc, function(node) {
  1940 + if (node.__location && node.__location.start >= 0) {
  1941 + node.__locationDetail = getLineAndColumn(htmlString, node.__location.start);
  1942 + if (href) {
  1943 + node.__ownerDocument = href;
  1944 + }
  1945 + }
  1946 + });
  1947 +
  1948 + var registry = {
  1949 + base: [],
  1950 + template: [],
  1951 + script: [],
  1952 + style: [],
  1953 + import: [],
  1954 + 'dom-module': []};
  1955 +
  1956 + var queue = [].concat(doc.childNodes);
  1957 + var nextNode;
  1958 + while (queue.length > 0) {
  1959 + nextNode = queue.shift();
  1960 + if (nextNode && nextNode.tagName) {
  1961 + queue = queue.concat(nextNode.childNodes);
  1962 + addNode(nextNode, registry);
  1963 + }
  1964 + }
  1965 + registry.ast = doc;
  1966 + return registry;
  1967 +};
  1968 +
  1969 +module.exports = importParse;
  1970 +
  1971 +},{"dom5":38}],11:[function(require,module,exports){
  1972 +/**
  1973 + * @license
  1974 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  1975 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  1976 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  1977 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  1978 + * Code distributed by Google as part of the polymer project is also
  1979 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  1980 + */
  1981 +/**
  1982 +* Finds and annotates the Polymer() and modulate() calls in javascript.
  1983 +*/
  1984 +// jshint node: true
  1985 +'use strict';
  1986 +var espree = require('espree');
  1987 +var estraverse = require('estraverse');
  1988 +
  1989 +var behaviorFinder = require('./behavior-finder');
  1990 +var elementFinder = require('./element-finder');
  1991 +var featureFinder = require('./feature-finder');
  1992 +
  1993 +function traverse(visitorRegistries) {
  1994 + var visitor;
  1995 + function applyVisitors(name, node, parent) {
  1996 + var returnVal;
  1997 + for (var i = 0; i < visitorRegistries.length; i++) {
  1998 + if (name in visitorRegistries[i]) {
  1999 + returnVal = visitorRegistries[i][name](node, parent);
  2000 + if (returnVal) {
  2001 + return returnVal;
  2002 + }
  2003 + }
  2004 + }
  2005 + }
  2006 + return {
  2007 + enter: function(node, parent) {
  2008 + visitor = 'enter' + node.type;
  2009 + return applyVisitors(visitor, node, parent);
  2010 + },
  2011 + leave: function(node, parent) {
  2012 + visitor = 'leave' + node.type;
  2013 + return applyVisitors(visitor, node, parent);
  2014 + }
  2015 + };
  2016 +}
  2017 +
  2018 +var jsParse = function jsParse(jsString) {
  2019 + var script = espree.parse(jsString, {
  2020 + attachComment: true,
  2021 + comment: true,
  2022 + loc: true,
  2023 + ecmaFeatures: {
  2024 + arrowFunctions: true,
  2025 + blockBindings: true,
  2026 + destructuring: true,
  2027 + regexYFlag: true,
  2028 + regexUFlag: true,
  2029 + templateStrings: true,
  2030 + binaryLiterals: true,
  2031 + unicodeCodePointEscapes: true,
  2032 + defaultParams: true,
  2033 + restParams: true,
  2034 + forOf: true,
  2035 + objectLiteralComputedProperties: true,
  2036 + objectLiteralShorthandMethods: true,
  2037 + objectLiteralShorthandProperties: true,
  2038 + objectLiteralDuplicateProperties: true,
  2039 + generators: true,
  2040 + spread: true,
  2041 + classes: true,
  2042 + modules: true,
  2043 + jsx: true,
  2044 + globalReturn: true,
  2045 + }
  2046 + });
  2047 +
  2048 + var featureInfo = featureFinder();
  2049 + var behaviorInfo = behaviorFinder();
  2050 + var elementInfo = elementFinder();
  2051 +
  2052 + var visitors = [featureInfo, behaviorInfo, elementInfo].map(function(info) {
  2053 + return info.visitors;
  2054 + });
  2055 + estraverse.traverse(script, traverse(visitors));
  2056 +
  2057 + return {
  2058 + behaviors: behaviorInfo.behaviors,
  2059 + elements: elementInfo.elements,
  2060 + features: featureInfo.features,
  2061 + };
  2062 +};
  2063 +
  2064 +module.exports = jsParse;
  2065 +
  2066 +},{"./behavior-finder":4,"./element-finder":6,"./feature-finder":8,"espree":61,"estraverse":72}],12:[function(require,module,exports){
  2067 +/**
  2068 + * @license
  2069 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  2070 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  2071 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  2072 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  2073 + * Code distributed by Google as part of the polymer project is also
  2074 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  2075 + */
  2076 +// jshint node: true
  2077 +'use strict';
  2078 +
  2079 +var doctrine = require('doctrine');
  2080 +
  2081 +/**
  2082 + * An annotated JSDoc block tag, all fields are optionally processed except for
  2083 + * the tag:
  2084 + *
  2085 + * @TAG {TYPE} NAME DESC
  2086 + *
  2087 + * `line` and `col` indicate the position of the first character of text that
  2088 + * the tag was extracted from - relative to the first character of the comment
  2089 + * contents (e.g. the value of `desc` on a descriptor node). Lines are
  2090 + * 1-indexed.
  2091 + *
  2092 + * @typedef {{
  2093 + * tag: string,
  2094 + * type: ?string,
  2095 + * name: ?string,
  2096 + * description: ?string,
  2097 + * }}
  2098 + */
  2099 +var JsdocTag;
  2100 +
  2101 +/**
  2102 + * The parsed representation of a JSDoc comment.
  2103 + *
  2104 + * @typedef {{
  2105 + * description: ?string,
  2106 + * tags: Array<JsdocTag>,
  2107 + * }}
  2108 + */
  2109 +var JsdocAnnotation;
  2110 +
  2111 +/**
  2112 + * doctrine configuration,
  2113 + * CURRENTLY UNUSED BECAUSE PRIVATE
  2114 + */
  2115 +// function configureDoctrine() {
  2116 +
  2117 +// // @hero [path/to/image]
  2118 +// doctrine.Rules['hero'] = ['parseNamePathOptional', 'ensureEnd'];
  2119 +
  2120 +// // // @demo [path/to/demo] [Demo title]
  2121 +// doctrine.Rules['demo'] = ['parseNamePathOptional', 'parseDescription', 'ensureEnd'];
  2122 +
  2123 +// // // @polymerBehavior [Polymer.BehaviorName]
  2124 +// doctrine.Rules['polymerBehavior'] = ['parseNamePathOptional', 'ensureEnd'];
  2125 +// }
  2126 +// configureDoctrine();
  2127 +
  2128 +// @demo [path] [title]
  2129 +function parseDemo(tag) {
  2130 + var match = (tag.description || "").match(/^\s*(\S*)\s*(.*)$/);
  2131 + return {
  2132 + tag: 'demo',
  2133 + type: null,
  2134 + name: match ? match[1] : null,
  2135 + description: match ? match[2] : null
  2136 + };
  2137 +}
  2138 +
  2139 +// @hero [path]
  2140 +function parseHero(tag) {
  2141 + return {
  2142 + tag: tag.title,
  2143 + type: null,
  2144 + name: tag.description,
  2145 + description: null
  2146 + };
  2147 +}
  2148 +
  2149 +// @polymerBehavior [name]
  2150 +function parsePolymerBehavior(tag) {
  2151 + return {
  2152 + tag: tag.title,
  2153 + type: null,
  2154 + name: tag.description,
  2155 + description: null
  2156 + };
  2157 +}
  2158 +
  2159 +// @pseudoElement name
  2160 +function parsePseudoElement(tag) {
  2161 + return {
  2162 + tag: tag.title,
  2163 + type: null,
  2164 + name: tag.description,
  2165 + description: null
  2166 + };
  2167 +}
  2168 +
  2169 +var CUSTOM_TAGS = {
  2170 + demo: parseDemo,
  2171 + hero: parseHero,
  2172 + polymerBehavior: parsePolymerBehavior,
  2173 + pseudoElement: parsePseudoElement
  2174 +};
  2175 +
  2176 +/**
  2177 + * Convert doctrine tags to hydrolysis tag format
  2178 + */
  2179 +function _tagsToHydroTags(tags) {
  2180 + if (!tags)
  2181 + return null;
  2182 + return tags.map( function(tag) {
  2183 + if (tag.title in CUSTOM_TAGS) {
  2184 + return CUSTOM_TAGS[tag.title](tag);
  2185 + }
  2186 + else {
  2187 + return {
  2188 + tag: tag.title,
  2189 + type: tag.type ? doctrine.type.stringify(tag.type) : null,
  2190 + name: tag.name,
  2191 + description: tag.description,
  2192 + };
  2193 + }
  2194 + });
  2195 +}
  2196 +
  2197 +/**
  2198 + * removes leading *, and any space before it
  2199 + * @param {string} description -- js doc description
  2200 + */
  2201 +function _removeLeadingAsterisks(description) {
  2202 + if ((typeof description) !== 'string')
  2203 + return description;
  2204 +
  2205 + return description
  2206 + .split('\n')
  2207 + .map( function(line) {
  2208 + // remove leading '\s*' from each line
  2209 + var match = line.match(/^[\s]*\*\s?(.*)$/);
  2210 + return match ? match[1] : line;
  2211 + })
  2212 + .join('\n');
  2213 +}
  2214 +
  2215 +/**
  2216 + * Given a JSDoc string (minus opening/closing comment delimiters), extract its
  2217 + * description and tags.
  2218 + *
  2219 + * @param {string} docs
  2220 + * @return {?JsdocAnnotation}
  2221 + */
  2222 +function parseJsdoc(docs) {
  2223 + docs = _removeLeadingAsterisks(docs);
  2224 + var d = doctrine.parse(docs, {
  2225 + unwrap: false,
  2226 + lineNumber: true,
  2227 + preserveWhitespace: true
  2228 + });
  2229 + return {
  2230 + description: d.description,
  2231 + tags: _tagsToHydroTags(d.tags)
  2232 + };
  2233 +}
  2234 +
  2235 +// Utility
  2236 +
  2237 +/**
  2238 + * @param {JsdocAnnotation} jsdoc
  2239 + * @param {string} tagName
  2240 + * @return {boolean}
  2241 + */
  2242 +function hasTag(jsdoc, tagName) {
  2243 + if (!jsdoc || !jsdoc.tags) return false;
  2244 + return jsdoc.tags.some(function(tag) { return tag.tag === tagName; });
  2245 +}
  2246 +
  2247 +/**
  2248 + * Finds the first JSDoc tag matching `name` and returns its value at `key`.
  2249 + *
  2250 + * @param {JsdocAnnotation} jsdoc
  2251 + * @param {string} tagName
  2252 + * @param {string=} key If omitted, the entire tag object is returned.
  2253 + * @return {?string|Object}
  2254 + */
  2255 +function getTag(jsdoc, tagName, key) {
  2256 + if (!jsdoc || !jsdoc.tags) return false;
  2257 + for (var i = 0; i < jsdoc.tags.length; i++) {
  2258 + var tag = jsdoc.tags[i];
  2259 + if (tag.tag === tagName) {
  2260 + return key ? tag[key] : tag;
  2261 + }
  2262 + }
  2263 + return null;
  2264 +}
  2265 +
  2266 +/**
  2267 + * @param {?string} text
  2268 + * @return {?string}
  2269 + */
  2270 +function unindent(text) {
  2271 + if (!text) return text;
  2272 + var lines = text.replace(/\t/g, ' ').split('\n');
  2273 + var indent = lines.reduce(function(prev, line) {
  2274 + if (/^\s*$/.test(line)) return prev; // Completely ignore blank lines.
  2275 +
  2276 + var lineIndent = line.match(/^(\s*)/)[0].length;
  2277 + if (prev === null) return lineIndent;
  2278 + return lineIndent < prev ? lineIndent : prev;
  2279 + }, null);
  2280 +
  2281 + return lines.map(function(l) { return l.substr(indent); }).join('\n');
  2282 +}
  2283 +
  2284 +module.exports = {
  2285 + getTag: getTag,
  2286 + hasTag: hasTag,
  2287 + parseJsdoc: parseJsdoc,
  2288 + unindent: unindent
  2289 +};
  2290 +
  2291 +},{"doctrine":29}],13:[function(require,module,exports){
  2292 +(function (global){
  2293 +/**
  2294 + * @license
  2295 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  2296 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  2297 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  2298 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  2299 + * Code distributed by Google as part of the polymer project is also
  2300 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  2301 + */
  2302 +
  2303 +// jshint node:true
  2304 +'use strict';
  2305 +
  2306 +// jshint -W079
  2307 +// Promise polyfill
  2308 +var Promise = global.Promise || require('es6-promise').Promise;
  2309 +// jshint +W079
  2310 +
  2311 +function Deferred() {
  2312 + var self = this;
  2313 + this.promise = new Promise(function(resolve, reject) {
  2314 + self.resolve = resolve;
  2315 + self.reject = reject;
  2316 + });
  2317 +}
  2318 +
  2319 +/**
  2320 + * An object that knows how to resolve resources.
  2321 + * @typedef {Object} Resolver
  2322 + * @memberof hydrolysis
  2323 + * @property {function(string, Deferred): boolean} accept Attempt to resolve
  2324 + * `deferred` with the contents the specified URL. Returns false if the
  2325 + * Resolver is unable to resolve the URL.
  2326 + */
  2327 +
  2328 +
  2329 +/**
  2330 + * A FileLoader lets you resolve URLs with a set of potential resolvers.
  2331 + * @constructor
  2332 + * @memberof hydrolysis
  2333 + */
  2334 +function FileLoader() {
  2335 + this.resolvers = [];
  2336 + // map url -> Deferred
  2337 + this.requests = {};
  2338 +}
  2339 +FileLoader.prototype = {
  2340 +
  2341 + /**
  2342 + * Add an instance of a Resolver class to the list of url resolvers
  2343 + *
  2344 + * Ordering of resolvers is most to least recently added
  2345 + * The first resolver to "accept" the url wins.
  2346 + * @param {Resolver} resolver The resolver to add.
  2347 + */
  2348 + addResolver: function(resolver) {
  2349 + this.resolvers.push(resolver);
  2350 + },
  2351 +
  2352 + /**
  2353 + * Return a promise for an absolute url
  2354 + *
  2355 + * Url requests are deduplicated by the loader, returning the same Promise for
  2356 + * identical urls
  2357 + *
  2358 + * @param {string} url The absolute url to request.
  2359 + * @return {Promise.<string>} A promise that resolves to the contents of the URL.
  2360 + */
  2361 + request: function(uri) {
  2362 + var promise;
  2363 +
  2364 + if (!(uri in this.requests)) {
  2365 + var handled = false;
  2366 + var deferred = new Deferred();
  2367 + this.requests[uri] = deferred;
  2368 +
  2369 + // loop backwards through resolvers until one "accepts" the request
  2370 + for (var i = this.resolvers.length - 1, r; i >= 0; i--) {
  2371 + r = this.resolvers[i];
  2372 + if (r.accept(uri, deferred)) {
  2373 + handled = true;
  2374 + break;
  2375 + }
  2376 + }
  2377 +
  2378 + if (!handled) {
  2379 + deferred.reject('no resolver found');
  2380 + }
  2381 +
  2382 + promise = deferred.promise;
  2383 + } else {
  2384 + promise = this.requests[uri].promise;
  2385 + }
  2386 +
  2387 + return promise;
  2388 + }
  2389 +};
  2390 +
  2391 +module.exports = FileLoader;
  2392 +
  2393 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2394 +
  2395 +},{"es6-promise":60}],14:[function(require,module,exports){
  2396 +/**
  2397 + * @license
  2398 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  2399 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  2400 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  2401 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  2402 + * Code distributed by Google as part of the polymer project is also
  2403 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  2404 + */
  2405 +
  2406 +// jshint node:true
  2407 +'use strict';
  2408 +
  2409 +var fs = require('fs');
  2410 +var path = require('path');
  2411 +var url = require('url');
  2412 +
  2413 +function getFile(filePath, deferred, secondPath) {
  2414 + fs.readFile(filePath, 'utf-8', function(err, content) {
  2415 + if (err) {
  2416 + if (secondPath) {
  2417 + getFile(secondPath, deferred);
  2418 + } else {
  2419 + console.log("ERROR finding " + filePath);
  2420 + deferred.reject(err);
  2421 + }
  2422 + } else {
  2423 + deferred.resolve(content);
  2424 + }
  2425 + });
  2426 +}
  2427 +
  2428 +/**
  2429 + * Returns true if `patha` is a sibling or aunt of `pathb`.
  2430 + * @return {boolean}
  2431 + */
  2432 +function isSiblingOrAunt(patha, pathb) {
  2433 + var parent = path.dirname(patha);
  2434 + if (pathb.indexOf(patha) === -1 && pathb.indexOf(parent) === 0) {
  2435 + return true;
  2436 + }
  2437 + return false;
  2438 +}
  2439 +
  2440 +/**
  2441 + * Change `localPath` from a sibling of `basePath` to be a child of
  2442 + * `basePath` joined with `redirect`.
  2443 + * @return {string}
  2444 + */
  2445 +function redirectSibling(basePath, localPath, redirect) {
  2446 + var parent = path.dirname(basePath);
  2447 + var redirected = path.join(basePath, redirect, localPath.slice(parent.length));
  2448 + return redirected;
  2449 +}
  2450 +
  2451 +/**
  2452 + * Resolves requests via the file system.
  2453 + * @constructor
  2454 + * @memberof hydrolysis
  2455 + * @param {Object} config configuration options.
  2456 + * @param {string} config.host Hostname to match for absolute urls.
  2457 + * Matches "/" by default
  2458 + * @param {string} config.basePath Prefix directory for components in url.
  2459 + * Defaults to "/".
  2460 + * @param {string} config.root Filesystem root to search. Defaults to the
  2461 + * current working directory.
  2462 + * @param {string} config.redirect Where to redirect lookups to siblings.
  2463 + */
  2464 +function FSResolver(config) {
  2465 + this.config = config || {};
  2466 +}
  2467 +FSResolver.prototype = {
  2468 + accept: function(uri, deferred) {
  2469 + var parsed = url.parse(uri);
  2470 + var host = this.config.host;
  2471 + var base = this.config.basePath && decodeURIComponent(this.config.basePath);
  2472 + var root = this.config.root && path.normalize(this.config.root);
  2473 + var redirect = this.config.redirect;
  2474 +
  2475 + var local;
  2476 +
  2477 + if (!parsed.hostname || parsed.hostname === host) {
  2478 + local = parsed.pathname;
  2479 + }
  2480 +
  2481 + if (local) {
  2482 + // un-escape HTML escapes
  2483 + local = decodeURIComponent(local);
  2484 +
  2485 + if (base) {
  2486 + local = path.relative(base, local);
  2487 + }
  2488 + if (root) {
  2489 + local = path.join(root, local);
  2490 + }
  2491 +
  2492 + var backup;
  2493 + if (redirect && isSiblingOrAunt(root, local)) {
  2494 + backup = redirectSibling(root, local, redirect);
  2495 + }
  2496 +
  2497 + getFile(local, deferred, backup);
  2498 + return true;
  2499 + }
  2500 +
  2501 + return false;
  2502 + }
  2503 +};
  2504 +
  2505 +module.exports = FSResolver;
  2506 +
  2507 +},{"fs":17,"path":20,"url":26}],15:[function(require,module,exports){
  2508 +/**
  2509 + * @license
  2510 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  2511 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  2512 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  2513 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  2514 + * Code distributed by Google as part of the polymer project is also
  2515 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  2516 + */
  2517 +
  2518 +// jshint node:true
  2519 +'use strict';
  2520 +
  2521 +/**
  2522 + * A resolver that resolves to null any uri matching config.
  2523 + * @constructor
  2524 + * @memberof hydrolysis
  2525 + * @param {string} config The url to `accept`.
  2526 + */
  2527 +function NoopResolver(config) {
  2528 + this.config = config;
  2529 +}
  2530 +
  2531 +NoopResolver.prototype = {
  2532 +
  2533 + /**
  2534 + * @param {string} uri The absolute URI being requested.
  2535 + * @param {!Deferred} deferred The deferred promise that should be resolved if
  2536 + * this resolver handles the URI.
  2537 + * @return {boolean} Whether the URI is handled by this resolver.
  2538 + */
  2539 + accept: function(uri, deferred) {
  2540 + if (!this.config.test) {
  2541 + if (uri.search(this.config) == -1) {
  2542 + return false;
  2543 + }
  2544 + } else if (!this.config.test(uri)) return false;
  2545 +
  2546 + deferred.resolve('');
  2547 + return true;
  2548 + }
  2549 +};
  2550 +
  2551 +module.exports = NoopResolver;
  2552 +
  2553 +},{}],16:[function(require,module,exports){
  2554 +/**
  2555 + * @license
  2556 + * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
  2557 + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
  2558 + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
  2559 + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
  2560 + * Code distributed by Google as part of the polymer project is also
  2561 + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
  2562 + */
  2563 +
  2564 +// jshint node:true
  2565 +'use strict';
  2566 +
  2567 +function getFile(url, deferred, config) {
  2568 + /* global XMLHttpRequest:false */
  2569 + var x = new XMLHttpRequest();
  2570 + x.onload = function() {
  2571 + var status = x.status || 0;
  2572 + if (status >= 200 && status < 300) {
  2573 + deferred.resolve(x.response);
  2574 + } else {
  2575 + deferred.reject('xhr status: ' + status);
  2576 + }
  2577 + };
  2578 + x.onerror = function(e) {
  2579 + deferred.reject(e);
  2580 + };
  2581 + x.open('GET', url, true);
  2582 + if (config && config.responseType) {
  2583 + x.responseType = config.responseType;
  2584 + }
  2585 + x.send();
  2586 +}
  2587 +
  2588 +/**
  2589 + * Construct a resolver that requests resources over XHR.
  2590 + * @constructor
  2591 + * @memberof hydrolysis
  2592 + * @param {Object} config configuration arguments.
  2593 + * @param {string} config.responseType Type of object to be returned by the
  2594 + * XHR. Defaults to 'text', accepts 'document', 'arraybuffer', and 'json'.
  2595 + */
  2596 +function XHRResolver(config) {
  2597 + this.config = config;
  2598 +}
  2599 +XHRResolver.prototype = {
  2600 + accept: function(uri, deferred) {
  2601 + getFile(uri, deferred, this.config);
  2602 + return true;
  2603 + }
  2604 +};
  2605 +
  2606 +module.exports = XHRResolver;
  2607 +
  2608 +},{}],17:[function(require,module,exports){
  2609 +
  2610 +},{}],18:[function(require,module,exports){
  2611 +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
  2612 +//
  2613 +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
  2614 +//
  2615 +// Originally from narwhal.js (http://narwhaljs.org)
  2616 +// Copyright (c) 2009 Thomas Robinson <280north.com>
  2617 +//
  2618 +// Permission is hereby granted, free of charge, to any person obtaining a copy
  2619 +// of this software and associated documentation files (the 'Software'), to
  2620 +// deal in the Software without restriction, including without limitation the
  2621 +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  2622 +// sell copies of the Software, and to permit persons to whom the Software is
  2623 +// furnished to do so, subject to the following conditions:
  2624 +//
  2625 +// The above copyright notice and this permission notice shall be included in
  2626 +// all copies or substantial portions of the Software.
  2627 +//
  2628 +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  2629 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  2630 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  2631 +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  2632 +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  2633 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  2634 +
  2635 +// when used in node, this will actually load the util module we depend on
  2636 +// versus loading the builtin util module as happens otherwise
  2637 +// this is a bug in node module loading as far as I am concerned
  2638 +var util = require('util/');
  2639 +
  2640 +var pSlice = Array.prototype.slice;
  2641 +var hasOwn = Object.prototype.hasOwnProperty;
  2642 +
  2643 +// 1. The assert module provides functions that throw
  2644 +// AssertionError's when particular conditions are not met. The
  2645 +// assert module must conform to the following interface.
  2646 +
  2647 +var assert = module.exports = ok;
  2648 +
  2649 +// 2. The AssertionError is defined in assert.
  2650 +// new assert.AssertionError({ message: message,
  2651 +// actual: actual,
  2652 +// expected: expected })
  2653 +
  2654 +assert.AssertionError = function AssertionError(options) {
  2655 + this.name = 'AssertionError';
  2656 + this.actual = options.actual;
  2657 + this.expected = options.expected;
  2658 + this.operator = options.operator;
  2659 + if (options.message) {
  2660 + this.message = options.message;
  2661 + this.generatedMessage = false;
  2662 + } else {
  2663 + this.message = getMessage(this);
  2664 + this.generatedMessage = true;
  2665 + }
  2666 + var stackStartFunction = options.stackStartFunction || fail;
  2667 +
  2668 + if (Error.captureStackTrace) {
  2669 + Error.captureStackTrace(this, stackStartFunction);
  2670 + }
  2671 + else {
  2672 + // non v8 browsers so we can have a stacktrace
  2673 + var err = new Error();
  2674 + if (err.stack) {
  2675 + var out = err.stack;
  2676 +
  2677 + // try to strip useless frames
  2678 + var fn_name = stackStartFunction.name;
  2679 + var idx = out.indexOf('\n' + fn_name);
  2680 + if (idx >= 0) {
  2681 + // once we have located the function frame
  2682 + // we need to strip out everything before it (and its line)
  2683 + var next_line = out.indexOf('\n', idx + 1);
  2684 + out = out.substring(next_line + 1);
  2685 + }
  2686 +
  2687 + this.stack = out;
  2688 + }
  2689 + }
  2690 +};
  2691 +
  2692 +// assert.AssertionError instanceof Error
  2693 +util.inherits(assert.AssertionError, Error);
  2694 +
  2695 +function replacer(key, value) {
  2696 + if (util.isUndefined(value)) {
  2697 + return '' + value;
  2698 + }
  2699 + if (util.isNumber(value) && !isFinite(value)) {
  2700 + return value.toString();
  2701 + }
  2702 + if (util.isFunction(value) || util.isRegExp(value)) {
  2703 + return value.toString();
  2704 + }
  2705 + return value;
  2706 +}
  2707 +
  2708 +function truncate(s, n) {
  2709 + if (util.isString(s)) {
  2710 + return s.length < n ? s : s.slice(0, n);
  2711 + } else {
  2712 + return s;
  2713 + }
  2714 +}
  2715 +
  2716 +function getMessage(self) {
  2717 + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
  2718 + self.operator + ' ' +
  2719 + truncate(JSON.stringify(self.expected, replacer), 128);
  2720 +}
  2721 +
  2722 +// At present only the three keys mentioned above are used and
  2723 +// understood by the spec. Implementations or sub modules can pass
  2724 +// other keys to the AssertionError's constructor - they will be
  2725 +// ignored.
  2726 +
  2727 +// 3. All of the following functions must throw an AssertionError
  2728 +// when a corresponding condition is not met, with a message that
  2729 +// may be undefined if not provided. All assertion methods provide
  2730 +// both the actual and expected values to the assertion error for
  2731 +// display purposes.
  2732 +
  2733 +function fail(actual, expected, message, operator, stackStartFunction) {
  2734 + throw new assert.AssertionError({
  2735 + message: message,
  2736 + actual: actual,
  2737 + expected: expected,
  2738 + operator: operator,
  2739 + stackStartFunction: stackStartFunction
  2740 + });
  2741 +}
  2742 +
  2743 +// EXTENSION! allows for well behaved errors defined elsewhere.
  2744 +assert.fail = fail;
  2745 +
  2746 +// 4. Pure assertion tests whether a value is truthy, as determined
  2747 +// by !!guard.
  2748 +// assert.ok(guard, message_opt);
  2749 +// This statement is equivalent to assert.equal(true, !!guard,
  2750 +// message_opt);. To test strictly for the value true, use
  2751 +// assert.strictEqual(true, guard, message_opt);.
  2752 +
  2753 +function ok(value, message) {
  2754 + if (!value) fail(value, true, message, '==', assert.ok);
  2755 +}
  2756 +assert.ok = ok;
  2757 +
  2758 +// 5. The equality assertion tests shallow, coercive equality with
  2759 +// ==.
  2760 +// assert.equal(actual, expected, message_opt);
  2761 +
  2762 +assert.equal = function equal(actual, expected, message) {
  2763 + if (actual != expected) fail(actual, expected, message, '==', assert.equal);
  2764 +};
  2765 +
  2766 +// 6. The non-equality assertion tests for whether two objects are not equal
  2767 +// with != assert.notEqual(actual, expected, message_opt);
  2768 +
  2769 +assert.notEqual = function notEqual(actual, expected, message) {
  2770 + if (actual == expected) {
  2771 + fail(actual, expected, message, '!=', assert.notEqual);
  2772 + }
  2773 +};
  2774 +
  2775 +// 7. The equivalence assertion tests a deep equality relation.
  2776 +// assert.deepEqual(actual, expected, message_opt);
  2777 +
  2778 +assert.deepEqual = function deepEqual(actual, expected, message) {
  2779 + if (!_deepEqual(actual, expected)) {
  2780 + fail(actual, expected, message, 'deepEqual', assert.deepEqual);
  2781 + }
  2782 +};
  2783 +
  2784 +function _deepEqual(actual, expected) {
  2785 + // 7.1. All identical values are equivalent, as determined by ===.
  2786 + if (actual === expected) {
  2787 + return true;
  2788 +
  2789 + } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
  2790 + if (actual.length != expected.length) return false;
  2791 +
  2792 + for (var i = 0; i < actual.length; i++) {
  2793 + if (actual[i] !== expected[i]) return false;
  2794 + }
  2795 +
  2796 + return true;
  2797 +
  2798 + // 7.2. If the expected value is a Date object, the actual value is
  2799 + // equivalent if it is also a Date object that refers to the same time.
  2800 + } else if (util.isDate(actual) && util.isDate(expected)) {
  2801 + return actual.getTime() === expected.getTime();
  2802 +
  2803 + // 7.3 If the expected value is a RegExp object, the actual value is
  2804 + // equivalent if it is also a RegExp object with the same source and
  2805 + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
  2806 + } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
  2807 + return actual.source === expected.source &&
  2808 + actual.global === expected.global &&
  2809 + actual.multiline === expected.multiline &&
  2810 + actual.lastIndex === expected.lastIndex &&
  2811 + actual.ignoreCase === expected.ignoreCase;
  2812 +
  2813 + // 7.4. Other pairs that do not both pass typeof value == 'object',
  2814 + // equivalence is determined by ==.
  2815 + } else if (!util.isObject(actual) && !util.isObject(expected)) {
  2816 + return actual == expected;
  2817 +
  2818 + // 7.5 For all other Object pairs, including Array objects, equivalence is
  2819 + // determined by having the same number of owned properties (as verified
  2820 + // with Object.prototype.hasOwnProperty.call), the same set of keys
  2821 + // (although not necessarily the same order), equivalent values for every
  2822 + // corresponding key, and an identical 'prototype' property. Note: this
  2823 + // accounts for both named and indexed properties on Arrays.
  2824 + } else {
  2825 + return objEquiv(actual, expected);
  2826 + }
  2827 +}
  2828 +
  2829 +function isArguments(object) {
  2830 + return Object.prototype.toString.call(object) == '[object Arguments]';
  2831 +}
  2832 +
  2833 +function objEquiv(a, b) {
  2834 + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
  2835 + return false;
  2836 + // an identical 'prototype' property.
  2837 + if (a.prototype !== b.prototype) return false;
  2838 + // if one is a primitive, the other must be same
  2839 + if (util.isPrimitive(a) || util.isPrimitive(b)) {
  2840 + return a === b;
  2841 + }
  2842 + var aIsArgs = isArguments(a),
  2843 + bIsArgs = isArguments(b);
  2844 + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
  2845 + return false;
  2846 + if (aIsArgs) {
  2847 + a = pSlice.call(a);
  2848 + b = pSlice.call(b);
  2849 + return _deepEqual(a, b);
  2850 + }
  2851 + var ka = objectKeys(a),
  2852 + kb = objectKeys(b),
  2853 + key, i;
  2854 + // having the same number of owned properties (keys incorporates
  2855 + // hasOwnProperty)
  2856 + if (ka.length != kb.length)
  2857 + return false;
  2858 + //the same set of keys (although not necessarily the same order),
  2859 + ka.sort();
  2860 + kb.sort();
  2861 + //~~~cheap key test
  2862 + for (i = ka.length - 1; i >= 0; i--) {
  2863 + if (ka[i] != kb[i])
  2864 + return false;
  2865 + }
  2866 + //equivalent values for every corresponding key, and
  2867 + //~~~possibly expensive deep test
  2868 + for (i = ka.length - 1; i >= 0; i--) {
  2869 + key = ka[i];
  2870 + if (!_deepEqual(a[key], b[key])) return false;
  2871 + }
  2872 + return true;
  2873 +}
  2874 +
  2875 +// 8. The non-equivalence assertion tests for any deep inequality.
  2876 +// assert.notDeepEqual(actual, expected, message_opt);
  2877 +
  2878 +assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
  2879 + if (_deepEqual(actual, expected)) {
  2880 + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
  2881 + }
  2882 +};
  2883 +
  2884 +// 9. The strict equality assertion tests strict equality, as determined by ===.
  2885 +// assert.strictEqual(actual, expected, message_opt);
  2886 +
  2887 +assert.strictEqual = function strictEqual(actual, expected, message) {
  2888 + if (actual !== expected) {
  2889 + fail(actual, expected, message, '===', assert.strictEqual);
  2890 + }
  2891 +};
  2892 +
  2893 +// 10. The strict non-equality assertion tests for strict inequality, as
  2894 +// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
  2895 +
  2896 +assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
  2897 + if (actual === expected) {
  2898 + fail(actual, expected, message, '!==', assert.notStrictEqual);
  2899 + }
  2900 +};
  2901 +
  2902 +function expectedException(actual, expected) {
  2903 + if (!actual || !expected) {
  2904 + return false;
  2905 + }
  2906 +
  2907 + if (Object.prototype.toString.call(expected) == '[object RegExp]') {
  2908 + return expected.test(actual);
  2909 + } else if (actual instanceof expected) {
  2910 + return true;
  2911 + } else if (expected.call({}, actual) === true) {
  2912 + return true;
  2913 + }
  2914 +
  2915 + return false;
  2916 +}
  2917 +
  2918 +function _throws(shouldThrow, block, expected, message) {
  2919 + var actual;
  2920 +
  2921 + if (util.isString(expected)) {
  2922 + message = expected;
  2923 + expected = null;
  2924 + }
  2925 +
  2926 + try {
  2927 + block();
  2928 + } catch (e) {
  2929 + actual = e;
  2930 + }
  2931 +
  2932 + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
  2933 + (message ? ' ' + message : '.');
  2934 +
  2935 + if (shouldThrow && !actual) {
  2936 + fail(actual, expected, 'Missing expected exception' + message);
  2937 + }
  2938 +
  2939 + if (!shouldThrow && expectedException(actual, expected)) {
  2940 + fail(actual, expected, 'Got unwanted exception' + message);
  2941 + }
  2942 +
  2943 + if ((shouldThrow && actual && expected &&
  2944 + !expectedException(actual, expected)) || (!shouldThrow && actual)) {
  2945 + throw actual;
  2946 + }
  2947 +}
  2948 +
  2949 +// 11. Expected to throw an error:
  2950 +// assert.throws(block, Error_opt, message_opt);
  2951 +
  2952 +assert.throws = function(block, /*optional*/error, /*optional*/message) {
  2953 + _throws.apply(this, [true].concat(pSlice.call(arguments)));
  2954 +};
  2955 +
  2956 +// EXTENSION! This is annoying to write outside this module.
  2957 +assert.doesNotThrow = function(block, /*optional*/message) {
  2958 + _throws.apply(this, [false].concat(pSlice.call(arguments)));
  2959 +};
  2960 +
  2961 +assert.ifError = function(err) { if (err) {throw err;}};
  2962 +
  2963 +var objectKeys = Object.keys || function (obj) {
  2964 + var keys = [];
  2965 + for (var key in obj) {
  2966 + if (hasOwn.call(obj, key)) keys.push(key);
  2967 + }
  2968 + return keys;
  2969 +};
  2970 +
  2971 +},{"util/":28}],19:[function(require,module,exports){
  2972 +if (typeof Object.create === 'function') {
  2973 + // implementation from standard node.js 'util' module
  2974 + module.exports = function inherits(ctor, superCtor) {
  2975 + ctor.super_ = superCtor
  2976 + ctor.prototype = Object.create(superCtor.prototype, {
  2977 + constructor: {
  2978 + value: ctor,
  2979 + enumerable: false,
  2980 + writable: true,
  2981 + configurable: true
  2982 + }
  2983 + });
  2984 + };
  2985 +} else {
  2986 + // old school shim for old browsers
  2987 + module.exports = function inherits(ctor, superCtor) {
  2988 + ctor.super_ = superCtor
  2989 + var TempCtor = function () {}
  2990 + TempCtor.prototype = superCtor.prototype
  2991 + ctor.prototype = new TempCtor()
  2992 + ctor.prototype.constructor = ctor
  2993 + }
  2994 +}
  2995 +
  2996 +},{}],20:[function(require,module,exports){
  2997 +(function (process){
  2998 +// Copyright Joyent, Inc. and other Node contributors.
  2999 +//
  3000 +// Permission is hereby granted, free of charge, to any person obtaining a
  3001 +// copy of this software and associated documentation files (the
  3002 +// "Software"), to deal in the Software without restriction, including
  3003 +// without limitation the rights to use, copy, modify, merge, publish,
  3004 +// distribute, sublicense, and/or sell copies of the Software, and to permit
  3005 +// persons to whom the Software is furnished to do so, subject to the
  3006 +// following conditions:
  3007 +//
  3008 +// The above copyright notice and this permission notice shall be included
  3009 +// in all copies or substantial portions of the Software.
  3010 +//
  3011 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  3012 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3013 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  3014 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  3015 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  3016 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  3017 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
  3018 +
  3019 +// resolves . and .. elements in a path array with directory names there
  3020 +// must be no slashes, empty elements, or device names (c:\) in the array
  3021 +// (so also no leading and trailing slashes - it does not distinguish
  3022 +// relative and absolute paths)
  3023 +function normalizeArray(parts, allowAboveRoot) {
  3024 + // if the path tries to go above the root, `up` ends up > 0
  3025 + var up = 0;
  3026 + for (var i = parts.length - 1; i >= 0; i--) {
  3027 + var last = parts[i];
  3028 + if (last === '.') {
  3029 + parts.splice(i, 1);
  3030 + } else if (last === '..') {
  3031 + parts.splice(i, 1);
  3032 + up++;
  3033 + } else if (up) {
  3034 + parts.splice(i, 1);
  3035 + up--;
  3036 + }
  3037 + }
  3038 +
  3039 + // if the path is allowed to go above the root, restore leading ..s
  3040 + if (allowAboveRoot) {
  3041 + for (; up--; up) {
  3042 + parts.unshift('..');
  3043 + }
  3044 + }
  3045 +
  3046 + return parts;
  3047 +}
  3048 +
  3049 +// Split a filename into [root, dir, basename, ext], unix version
  3050 +// 'root' is just a slash, or nothing.
  3051 +var splitPathRe =
  3052 + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  3053 +var splitPath = function(filename) {
  3054 + return splitPathRe.exec(filename).slice(1);
  3055 +};
  3056 +
  3057 +// path.resolve([from ...], to)
  3058 +// posix version
  3059 +exports.resolve = function() {
  3060 + var resolvedPath = '',
  3061 + resolvedAbsolute = false;
  3062 +
  3063 + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
  3064 + var path = (i >= 0) ? arguments[i] : process.cwd();
  3065 +
  3066 + // Skip empty and invalid entries
  3067 + if (typeof path !== 'string') {
  3068 + throw new TypeError('Arguments to path.resolve must be strings');
  3069 + } else if (!path) {
  3070 + continue;
  3071 + }
  3072 +
  3073 + resolvedPath = path + '/' + resolvedPath;
  3074 + resolvedAbsolute = path.charAt(0) === '/';
  3075 + }
  3076 +
  3077 + // At this point the path should be resolved to a full absolute path, but
  3078 + // handle relative paths to be safe (might happen when process.cwd() fails)
  3079 +
  3080 + // Normalize the path
  3081 + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
  3082 + return !!p;
  3083 + }), !resolvedAbsolute).join('/');
  3084 +
  3085 + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  3086 +};
  3087 +
  3088 +// path.normalize(path)
  3089 +// posix version
  3090 +exports.normalize = function(path) {
  3091 + var isAbsolute = exports.isAbsolute(path),
  3092 + trailingSlash = substr(path, -1) === '/';
  3093 +
  3094 + // Normalize the path
  3095 + path = normalizeArray(filter(path.split('/'), function(p) {
  3096 + return !!p;
  3097 + }), !isAbsolute).join('/');
  3098 +
  3099 + if (!path && !isAbsolute) {
  3100 + path = '.';
  3101 + }
  3102 + if (path && trailingSlash) {
  3103 + path += '/';
  3104 + }
  3105 +
  3106 + return (isAbsolute ? '/' : '') + path;
  3107 +};
  3108 +
  3109 +// posix version
  3110 +exports.isAbsolute = function(path) {
  3111 + return path.charAt(0) === '/';
  3112 +};
  3113 +
  3114 +// posix version
  3115 +exports.join = function() {
  3116 + var paths = Array.prototype.slice.call(arguments, 0);
  3117 + return exports.normalize(filter(paths, function(p, index) {
  3118 + if (typeof p !== 'string') {
  3119 + throw new TypeError('Arguments to path.join must be strings');
  3120 + }
  3121 + return p;
  3122 + }).join('/'));
  3123 +};
  3124 +
  3125 +
  3126 +// path.relative(from, to)
  3127 +// posix version
  3128 +exports.relative = function(from, to) {
  3129 + from = exports.resolve(from).substr(1);
  3130 + to = exports.resolve(to).substr(1);
  3131 +
  3132 + function trim(arr) {
  3133 + var start = 0;
  3134 + for (; start < arr.length; start++) {
  3135 + if (arr[start] !== '') break;
  3136 + }
  3137 +
  3138 + var end = arr.length - 1;
  3139 + for (; end >= 0; end--) {
  3140 + if (arr[end] !== '') break;
  3141 + }
  3142 +
  3143 + if (start > end) return [];
  3144 + return arr.slice(start, end - start + 1);
  3145 + }
  3146 +
  3147 + var fromParts = trim(from.split('/'));
  3148 + var toParts = trim(to.split('/'));
  3149 +
  3150 + var length = Math.min(fromParts.length, toParts.length);
  3151 + var samePartsLength = length;
  3152 + for (var i = 0; i < length; i++) {
  3153 + if (fromParts[i] !== toParts[i]) {
  3154 + samePartsLength = i;
  3155 + break;
  3156 + }
  3157 + }
  3158 +
  3159 + var outputParts = [];
  3160 + for (var i = samePartsLength; i < fromParts.length; i++) {
  3161 + outputParts.push('..');
  3162 + }
  3163 +
  3164 + outputParts = outputParts.concat(toParts.slice(samePartsLength));
  3165 +
  3166 + return outputParts.join('/');
  3167 +};
  3168 +
  3169 +exports.sep = '/';
  3170 +exports.delimiter = ':';
  3171 +
  3172 +exports.dirname = function(path) {
  3173 + var result = splitPath(path),
  3174 + root = result[0],
  3175 + dir = result[1];
  3176 +
  3177 + if (!root && !dir) {
  3178 + // No dirname whatsoever
  3179 + return '.';
  3180 + }
  3181 +
  3182 + if (dir) {
  3183 + // It has a dirname, strip trailing slash
  3184 + dir = dir.substr(0, dir.length - 1);
  3185 + }
  3186 +
  3187 + return root + dir;
  3188 +};
  3189 +
  3190 +
  3191 +exports.basename = function(path, ext) {
  3192 + var f = splitPath(path)[2];
  3193 + // TODO: make this comparison case-insensitive on windows?
  3194 + if (ext && f.substr(-1 * ext.length) === ext) {
  3195 + f = f.substr(0, f.length - ext.length);
  3196 + }
  3197 + return f;
  3198 +};
  3199 +
  3200 +
  3201 +exports.extname = function(path) {
  3202 + return splitPath(path)[3];
  3203 +};
  3204 +
  3205 +function filter (xs, f) {
  3206 + if (xs.filter) return xs.filter(f);
  3207 + var res = [];
  3208 + for (var i = 0; i < xs.length; i++) {
  3209 + if (f(xs[i], i, xs)) res.push(xs[i]);
  3210 + }
  3211 + return res;
  3212 +}
  3213 +
  3214 +// String.prototype.substr - negative index don't work in IE8
  3215 +var substr = 'ab'.substr(-1) === 'b'
  3216 + ? function (str, start, len) { return str.substr(start, len) }
  3217 + : function (str, start, len) {
  3218 + if (start < 0) start = str.length + start;
  3219 + return str.substr(start, len);
  3220 + }
  3221 +;
  3222 +
  3223 +}).call(this,require('_process'))
  3224 +
  3225 +},{"_process":21}],21:[function(require,module,exports){
  3226 +// shim for using process in browser
  3227 +
  3228 +var process = module.exports = {};
  3229 +var queue = [];
  3230 +var draining = false;
  3231 +
  3232 +function drainQueue() {
  3233 + if (draining) {
  3234 + return;
  3235 + }
  3236 + draining = true;
  3237 + var currentQueue;
  3238 + var len = queue.length;
  3239 + while(len) {
  3240 + currentQueue = queue;
  3241 + queue = [];
  3242 + var i = -1;
  3243 + while (++i < len) {
  3244 + currentQueue[i]();
  3245 + }
  3246 + len = queue.length;
  3247 + }
  3248 + draining = false;
  3249 +}
  3250 +process.nextTick = function (fun) {
  3251 + queue.push(fun);
  3252 + if (!draining) {
  3253 + setTimeout(drainQueue, 0);
  3254 + }
  3255 +};
  3256 +
  3257 +process.title = 'browser';
  3258 +process.browser = true;
  3259 +process.env = {};
  3260 +process.argv = [];
  3261 +process.version = ''; // empty string to avoid regexp issues
  3262 +process.versions = {};
  3263 +
  3264 +function noop() {}
  3265 +
  3266 +process.on = noop;
  3267 +process.addListener = noop;
  3268 +process.once = noop;
  3269 +process.off = noop;
  3270 +process.removeListener = noop;
  3271 +process.removeAllListeners = noop;
  3272 +process.emit = noop;
  3273 +
  3274 +process.binding = function (name) {
  3275 + throw new Error('process.binding is not supported');
  3276 +};
  3277 +
  3278 +// TODO(shtylman)
  3279 +process.cwd = function () { return '/' };
  3280 +process.chdir = function (dir) {
  3281 + throw new Error('process.chdir is not supported');
  3282 +};
  3283 +process.umask = function() { return 0; };
  3284 +
  3285 +},{}],22:[function(require,module,exports){
  3286 +(function (global){
  3287 +/*! http://mths.be/punycode v1.2.4 by @mathias */
  3288 +;(function(root) {
  3289 +
  3290 + /** Detect free variables */
  3291 + var freeExports = typeof exports == 'object' && exports;
  3292 + var freeModule = typeof module == 'object' && module &&
  3293 + module.exports == freeExports && module;
  3294 + var freeGlobal = typeof global == 'object' && global;
  3295 + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
  3296 + root = freeGlobal;
  3297 + }
  3298 +
  3299 + /**
  3300 + * The `punycode` object.
  3301 + * @name punycode
  3302 + * @type Object
  3303 + */
  3304 + var punycode,
  3305 +
  3306 + /** Highest positive signed 32-bit float value */
  3307 + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  3308 +
  3309 + /** Bootstring parameters */
  3310 + base = 36,
  3311 + tMin = 1,
  3312 + tMax = 26,
  3313 + skew = 38,
  3314 + damp = 700,
  3315 + initialBias = 72,
  3316 + initialN = 128, // 0x80
  3317 + delimiter = '-', // '\x2D'
  3318 +
  3319 + /** Regular expressions */
  3320 + regexPunycode = /^xn--/,
  3321 + regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
  3322 + regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
  3323 +
  3324 + /** Error messages */
  3325 + errors = {
  3326 + 'overflow': 'Overflow: input needs wider integers to process',
  3327 + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  3328 + 'invalid-input': 'Invalid input'
  3329 + },
  3330 +
  3331 + /** Convenience shortcuts */
  3332 + baseMinusTMin = base - tMin,
  3333 + floor = Math.floor,
  3334 + stringFromCharCode = String.fromCharCode,
  3335 +
  3336 + /** Temporary variable */
  3337 + key;
  3338 +
  3339 + /*--------------------------------------------------------------------------*/
  3340 +
  3341 + /**
  3342 + * A generic error utility function.
  3343 + * @private
  3344 + * @param {String} type The error type.
  3345 + * @returns {Error} Throws a `RangeError` with the applicable error message.
  3346 + */
  3347 + function error(type) {
  3348 + throw RangeError(errors[type]);
  3349 + }
  3350 +
  3351 + /**
  3352 + * A generic `Array#map` utility function.
  3353 + * @private
  3354 + * @param {Array} array The array to iterate over.
  3355 + * @param {Function} callback The function that gets called for every array
  3356 + * item.
  3357 + * @returns {Array} A new array of values returned by the callback function.
  3358 + */
  3359 + function map(array, fn) {
  3360 + var length = array.length;
  3361 + while (length--) {
  3362 + array[length] = fn(array[length]);
  3363 + }
  3364 + return array;
  3365 + }
  3366 +
  3367 + /**
  3368 + * A simple `Array#map`-like wrapper to work with domain name strings.
  3369 + * @private
  3370 + * @param {String} domain The domain name.
  3371 + * @param {Function} callback The function that gets called for every
  3372 + * character.
  3373 + * @returns {Array} A new string of characters returned by the callback
  3374 + * function.
  3375 + */
  3376 + function mapDomain(string, fn) {
  3377 + return map(string.split(regexSeparators), fn).join('.');
  3378 + }
  3379 +
  3380 + /**
  3381 + * Creates an array containing the numeric code points of each Unicode
  3382 + * character in the string. While JavaScript uses UCS-2 internally,
  3383 + * this function will convert a pair of surrogate halves (each of which
  3384 + * UCS-2 exposes as separate characters) into a single code point,
  3385 + * matching UTF-16.
  3386 + * @see `punycode.ucs2.encode`
  3387 + * @see <http://mathiasbynens.be/notes/javascript-encoding>
  3388 + * @memberOf punycode.ucs2
  3389 + * @name decode
  3390 + * @param {String} string The Unicode input string (UCS-2).
  3391 + * @returns {Array} The new array of code points.
  3392 + */
  3393 + function ucs2decode(string) {
  3394 + var output = [],
  3395 + counter = 0,
  3396 + length = string.length,
  3397 + value,
  3398 + extra;
  3399 + while (counter < length) {
  3400 + value = string.charCodeAt(counter++);
  3401 + if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  3402 + // high surrogate, and there is a next character
  3403 + extra = string.charCodeAt(counter++);
  3404 + if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  3405 + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  3406 + } else {
  3407 + // unmatched surrogate; only append this code unit, in case the next
  3408 + // code unit is the high surrogate of a surrogate pair
  3409 + output.push(value);
  3410 + counter--;
  3411 + }
  3412 + } else {
  3413 + output.push(value);
  3414 + }
  3415 + }
  3416 + return output;
  3417 + }
  3418 +
  3419 + /**
  3420 + * Creates a string based on an array of numeric code points.
  3421 + * @see `punycode.ucs2.decode`
  3422 + * @memberOf punycode.ucs2
  3423 + * @name encode
  3424 + * @param {Array} codePoints The array of numeric code points.
  3425 + * @returns {String} The new Unicode string (UCS-2).
  3426 + */
  3427 + function ucs2encode(array) {
  3428 + return map(array, function(value) {
  3429 + var output = '';
  3430 + if (value > 0xFFFF) {
  3431 + value -= 0x10000;
  3432 + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  3433 + value = 0xDC00 | value & 0x3FF;
  3434 + }
  3435 + output += stringFromCharCode(value);
  3436 + return output;
  3437 + }).join('');
  3438 + }
  3439 +
  3440 + /**
  3441 + * Converts a basic code point into a digit/integer.
  3442 + * @see `digitToBasic()`
  3443 + * @private
  3444 + * @param {Number} codePoint The basic numeric code point value.
  3445 + * @returns {Number} The numeric value of a basic code point (for use in
  3446 + * representing integers) in the range `0` to `base - 1`, or `base` if
  3447 + * the code point does not represent a value.
  3448 + */
  3449 + function basicToDigit(codePoint) {
  3450 + if (codePoint - 48 < 10) {
  3451 + return codePoint - 22;
  3452 + }
  3453 + if (codePoint - 65 < 26) {
  3454 + return codePoint - 65;
  3455 + }
  3456 + if (codePoint - 97 < 26) {
  3457 + return codePoint - 97;
  3458 + }
  3459 + return base;
  3460 + }
  3461 +
  3462 + /**
  3463 + * Converts a digit/integer into a basic code point.
  3464 + * @see `basicToDigit()`
  3465 + * @private
  3466 + * @param {Number} digit The numeric value of a basic code point.
  3467 + * @returns {Number} The basic code point whose value (when used for
  3468 + * representing integers) is `digit`, which needs to be in the range
  3469 + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  3470 + * used; else, the lowercase form is used. The behavior is undefined
  3471 + * if `flag` is non-zero and `digit` has no uppercase form.
  3472 + */
  3473 + function digitToBasic(digit, flag) {
  3474 + // 0..25 map to ASCII a..z or A..Z
  3475 + // 26..35 map to ASCII 0..9
  3476 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  3477 + }
  3478 +
  3479 + /**
  3480 + * Bias adaptation function as per section 3.4 of RFC 3492.
  3481 + * http://tools.ietf.org/html/rfc3492#section-3.4
  3482 + * @private
  3483 + */
  3484 + function adapt(delta, numPoints, firstTime) {
  3485 + var k = 0;
  3486 + delta = firstTime ? floor(delta / damp) : delta >> 1;
  3487 + delta += floor(delta / numPoints);
  3488 + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  3489 + delta = floor(delta / baseMinusTMin);
  3490 + }
  3491 + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  3492 + }
  3493 +
  3494 + /**
  3495 + * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  3496 + * symbols.
  3497 + * @memberOf punycode
  3498 + * @param {String} input The Punycode string of ASCII-only symbols.
  3499 + * @returns {String} The resulting string of Unicode symbols.
  3500 + */
  3501 + function decode(input) {
  3502 + // Don't use UCS-2
  3503 + var output = [],
  3504 + inputLength = input.length,
  3505 + out,
  3506 + i = 0,
  3507 + n = initialN,
  3508 + bias = initialBias,
  3509 + basic,
  3510 + j,
  3511 + index,
  3512 + oldi,
  3513 + w,
  3514 + k,
  3515 + digit,
  3516 + t,
  3517 + /** Cached calculation results */
  3518 + baseMinusT;
  3519 +
  3520 + // Handle the basic code points: let `basic` be the number of input code
  3521 + // points before the last delimiter, or `0` if there is none, then copy
  3522 + // the first basic code points to the output.
  3523 +
  3524 + basic = input.lastIndexOf(delimiter);
  3525 + if (basic < 0) {
  3526 + basic = 0;
  3527 + }
  3528 +
  3529 + for (j = 0; j < basic; ++j) {
  3530 + // if it's not a basic code point
  3531 + if (input.charCodeAt(j) >= 0x80) {
  3532 + error('not-basic');
  3533 + }
  3534 + output.push(input.charCodeAt(j));
  3535 + }
  3536 +
  3537 + // Main decoding loop: start just after the last delimiter if any basic code
  3538 + // points were copied; start at the beginning otherwise.
  3539 +
  3540 + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  3541 +
  3542 + // `index` is the index of the next character to be consumed.
  3543 + // Decode a generalized variable-length integer into `delta`,
  3544 + // which gets added to `i`. The overflow checking is easier
  3545 + // if we increase `i` as we go, then subtract off its starting
  3546 + // value at the end to obtain `delta`.
  3547 + for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  3548 +
  3549 + if (index >= inputLength) {
  3550 + error('invalid-input');
  3551 + }
  3552 +
  3553 + digit = basicToDigit(input.charCodeAt(index++));
  3554 +
  3555 + if (digit >= base || digit > floor((maxInt - i) / w)) {
  3556 + error('overflow');
  3557 + }
  3558 +
  3559 + i += digit * w;
  3560 + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  3561 +
  3562 + if (digit < t) {
  3563 + break;
  3564 + }
  3565 +
  3566 + baseMinusT = base - t;
  3567 + if (w > floor(maxInt / baseMinusT)) {
  3568 + error('overflow');
  3569 + }
  3570 +
  3571 + w *= baseMinusT;
  3572 +
  3573 + }
  3574 +
  3575 + out = output.length + 1;
  3576 + bias = adapt(i - oldi, out, oldi == 0);
  3577 +
  3578 + // `i` was supposed to wrap around from `out` to `0`,
  3579 + // incrementing `n` each time, so we'll fix that now:
  3580 + if (floor(i / out) > maxInt - n) {
  3581 + error('overflow');
  3582 + }
  3583 +
  3584 + n += floor(i / out);
  3585 + i %= out;
  3586 +
  3587 + // Insert `n` at position `i` of the output
  3588 + output.splice(i++, 0, n);
  3589 +
  3590 + }
  3591 +
  3592 + return ucs2encode(output);
  3593 + }
  3594 +
  3595 + /**
  3596 + * Converts a string of Unicode symbols to a Punycode string of ASCII-only
  3597 + * symbols.
  3598 + * @memberOf punycode
  3599 + * @param {String} input The string of Unicode symbols.
  3600 + * @returns {String} The resulting Punycode string of ASCII-only symbols.
  3601 + */
  3602 + function encode(input) {
  3603 + var n,
  3604 + delta,
  3605 + handledCPCount,
  3606 + basicLength,
  3607 + bias,
  3608 + j,
  3609 + m,
  3610 + q,
  3611 + k,
  3612 + t,
  3613 + currentValue,
  3614 + output = [],
  3615 + /** `inputLength` will hold the number of code points in `input`. */
  3616 + inputLength,
  3617 + /** Cached calculation results */
  3618 + handledCPCountPlusOne,
  3619 + baseMinusT,
  3620 + qMinusT;
  3621 +
  3622 + // Convert the input in UCS-2 to Unicode
  3623 + input = ucs2decode(input);
  3624 +
  3625 + // Cache the length
  3626 + inputLength = input.length;
  3627 +
  3628 + // Initialize the state
  3629 + n = initialN;
  3630 + delta = 0;
  3631 + bias = initialBias;
  3632 +
  3633 + // Handle the basic code points
  3634 + for (j = 0; j < inputLength; ++j) {
  3635 + currentValue = input[j];
  3636 + if (currentValue < 0x80) {
  3637 + output.push(stringFromCharCode(currentValue));
  3638 + }
  3639 + }
  3640 +
  3641 + handledCPCount = basicLength = output.length;
  3642 +
  3643 + // `handledCPCount` is the number of code points that have been handled;
  3644 + // `basicLength` is the number of basic code points.
  3645 +
  3646 + // Finish the basic string - if it is not empty - with a delimiter
  3647 + if (basicLength) {
  3648 + output.push(delimiter);
  3649 + }
  3650 +
  3651 + // Main encoding loop:
  3652 + while (handledCPCount < inputLength) {
  3653 +
  3654 + // All non-basic code points < n have been handled already. Find the next
  3655 + // larger one:
  3656 + for (m = maxInt, j = 0; j < inputLength; ++j) {
  3657 + currentValue = input[j];
  3658 + if (currentValue >= n && currentValue < m) {
  3659 + m = currentValue;
  3660 + }
  3661 + }
  3662 +
  3663 + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  3664 + // but guard against overflow
  3665 + handledCPCountPlusOne = handledCPCount + 1;
  3666 + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  3667 + error('overflow');
  3668 + }
  3669 +
  3670 + delta += (m - n) * handledCPCountPlusOne;
  3671 + n = m;
  3672 +
  3673 + for (j = 0; j < inputLength; ++j) {
  3674 + currentValue = input[j];
  3675 +
  3676 + if (currentValue < n && ++delta > maxInt) {
  3677 + error('overflow');
  3678 + }
  3679 +
  3680 + if (currentValue == n) {
  3681 + // Represent delta as a generalized variable-length integer
  3682 + for (q = delta, k = base; /* no condition */; k += base) {
  3683 + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  3684 + if (q < t) {
  3685 + break;
  3686 + }
  3687 + qMinusT = q - t;
  3688 + baseMinusT = base - t;
  3689 + output.push(
  3690 + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  3691 + );
  3692 + q = floor(qMinusT / baseMinusT);
  3693 + }
  3694 +
  3695 + output.push(stringFromCharCode(digitToBasic(q, 0)));
  3696 + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  3697 + delta = 0;
  3698 + ++handledCPCount;
  3699 + }
  3700 + }
  3701 +
  3702 + ++delta;
  3703 + ++n;
  3704 +
  3705 + }
  3706 + return output.join('');
  3707 + }
  3708 +
  3709 + /**
  3710 + * Converts a Punycode string representing a domain name to Unicode. Only the
  3711 + * Punycoded parts of the domain name will be converted, i.e. it doesn't
  3712 + * matter if you call it on a string that has already been converted to
  3713 + * Unicode.
  3714 + * @memberOf punycode
  3715 + * @param {String} domain The Punycode domain name to convert to Unicode.
  3716 + * @returns {String} The Unicode representation of the given Punycode
  3717 + * string.
  3718 + */
  3719 + function toUnicode(domain) {
  3720 + return mapDomain(domain, function(string) {
  3721 + return regexPunycode.test(string)
  3722 + ? decode(string.slice(4).toLowerCase())
  3723 + : string;
  3724 + });
  3725 + }
  3726 +
  3727 + /**
  3728 + * Converts a Unicode string representing a domain name to Punycode. Only the
  3729 + * non-ASCII parts of the domain name will be converted, i.e. it doesn't
  3730 + * matter if you call it with a domain that's already in ASCII.
  3731 + * @memberOf punycode
  3732 + * @param {String} domain The domain name to convert, as a Unicode string.
  3733 + * @returns {String} The Punycode representation of the given domain name.
  3734 + */
  3735 + function toASCII(domain) {
  3736 + return mapDomain(domain, function(string) {
  3737 + return regexNonASCII.test(string)
  3738 + ? 'xn--' + encode(string)
  3739 + : string;
  3740 + });
  3741 + }
  3742 +
  3743 + /*--------------------------------------------------------------------------*/
  3744 +
  3745 + /** Define the public API */
  3746 + punycode = {
  3747 + /**
  3748 + * A string representing the current Punycode.js version number.
  3749 + * @memberOf punycode
  3750 + * @type String
  3751 + */
  3752 + 'version': '1.2.4',
  3753 + /**
  3754 + * An object of methods to convert from JavaScript's internal character
  3755 + * representation (UCS-2) to Unicode code points, and back.
  3756 + * @see <http://mathiasbynens.be/notes/javascript-encoding>
  3757 + * @memberOf punycode
  3758 + * @type Object
  3759 + */
  3760 + 'ucs2': {
  3761 + 'decode': ucs2decode,
  3762 + 'encode': ucs2encode
  3763 + },
  3764 + 'decode': decode,
  3765 + 'encode': encode,
  3766 + 'toASCII': toASCII,
  3767 + 'toUnicode': toUnicode
  3768 + };
  3769 +
  3770 + /** Expose `punycode` */
  3771 + // Some AMD build optimizers, like r.js, check for specific condition patterns
  3772 + // like the following:
  3773 + if (
  3774 + typeof define == 'function' &&
  3775 + typeof define.amd == 'object' &&
  3776 + define.amd
  3777 + ) {
  3778 + define('punycode', function() {
  3779 + return punycode;
  3780 + });
  3781 + } else if (freeExports && !freeExports.nodeType) {
  3782 + if (freeModule) { // in Node.js or RingoJS v0.8.0+
  3783 + freeModule.exports = punycode;
  3784 + } else { // in Narwhal or RingoJS v0.7.0-
  3785 + for (key in punycode) {
  3786 + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  3787 + }
  3788 + }
  3789 + } else { // in Rhino or a web browser
  3790 + root.punycode = punycode;
  3791 + }
  3792 +
  3793 +}(this));
  3794 +
  3795 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3796 +
  3797 +},{}],23:[function(require,module,exports){
  3798 +// Copyright Joyent, Inc. and other Node contributors.
  3799 +//
  3800 +// Permission is hereby granted, free of charge, to any person obtaining a
  3801 +// copy of this software and associated documentation files (the
  3802 +// "Software"), to deal in the Software without restriction, including
  3803 +// without limitation the rights to use, copy, modify, merge, publish,
  3804 +// distribute, sublicense, and/or sell copies of the Software, and to permit
  3805 +// persons to whom the Software is furnished to do so, subject to the
  3806 +// following conditions:
  3807 +//
  3808 +// The above copyright notice and this permission notice shall be included
  3809 +// in all copies or substantial portions of the Software.
  3810 +//
  3811 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  3812 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3813 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  3814 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  3815 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  3816 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  3817 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
  3818 +
  3819 +'use strict';
  3820 +
  3821 +// If obj.hasOwnProperty has been overridden, then calling
  3822 +// obj.hasOwnProperty(prop) will break.
  3823 +// See: https://github.com/joyent/node/issues/1707
  3824 +function hasOwnProperty(obj, prop) {
  3825 + return Object.prototype.hasOwnProperty.call(obj, prop);
  3826 +}
  3827 +
  3828 +module.exports = function(qs, sep, eq, options) {
  3829 + sep = sep || '&';
  3830 + eq = eq || '=';
  3831 + var obj = {};
  3832 +
  3833 + if (typeof qs !== 'string' || qs.length === 0) {
  3834 + return obj;
  3835 + }
  3836 +
  3837 + var regexp = /\+/g;
  3838 + qs = qs.split(sep);
  3839 +
  3840 + var maxKeys = 1000;
  3841 + if (options && typeof options.maxKeys === 'number') {
  3842 + maxKeys = options.maxKeys;
  3843 + }
  3844 +
  3845 + var len = qs.length;
  3846 + // maxKeys <= 0 means that we should not limit keys count
  3847 + if (maxKeys > 0 && len > maxKeys) {
  3848 + len = maxKeys;
  3849 + }
  3850 +
  3851 + for (var i = 0; i < len; ++i) {
  3852 + var x = qs[i].replace(regexp, '%20'),
  3853 + idx = x.indexOf(eq),
  3854 + kstr, vstr, k, v;
  3855 +
  3856 + if (idx >= 0) {
  3857 + kstr = x.substr(0, idx);
  3858 + vstr = x.substr(idx + 1);
  3859 + } else {
  3860 + kstr = x;
  3861 + vstr = '';
  3862 + }
  3863 +
  3864 + k = decodeURIComponent(kstr);
  3865 + v = decodeURIComponent(vstr);
  3866 +
  3867 + if (!hasOwnProperty(obj, k)) {
  3868 + obj[k] = v;
  3869 + } else if (isArray(obj[k])) {
  3870 + obj[k].push(v);
  3871 + } else {
  3872 + obj[k] = [obj[k], v];
  3873 + }
  3874 + }
  3875 +
  3876 + return obj;
  3877 +};
  3878 +
  3879 +var isArray = Array.isArray || function (xs) {
  3880 + return Object.prototype.toString.call(xs) === '[object Array]';
  3881 +};
  3882 +
  3883 +},{}],24:[function(require,module,exports){
  3884 +// Copyright Joyent, Inc. and other Node contributors.
  3885 +//
  3886 +// Permission is hereby granted, free of charge, to any person obtaining a
  3887 +// copy of this software and associated documentation files (the
  3888 +// "Software"), to deal in the Software without restriction, including
  3889 +// without limitation the rights to use, copy, modify, merge, publish,
  3890 +// distribute, sublicense, and/or sell copies of the Software, and to permit
  3891 +// persons to whom the Software is furnished to do so, subject to the
  3892 +// following conditions:
  3893 +//
  3894 +// The above copyright notice and this permission notice shall be included
  3895 +// in all copies or substantial portions of the Software.
  3896 +//
  3897 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  3898 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3899 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  3900 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  3901 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  3902 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  3903 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
  3904 +
  3905 +'use strict';
  3906 +
  3907 +var stringifyPrimitive = function(v) {
  3908 + switch (typeof v) {
  3909 + case 'string':
  3910 + return v;
  3911 +
  3912 + case 'boolean':
  3913 + return v ? 'true' : 'false';
  3914 +
  3915 + case 'number':
  3916 + return isFinite(v) ? v : '';
  3917 +
  3918 + default:
  3919 + return '';
  3920 + }
  3921 +};
  3922 +
  3923 +module.exports = function(obj, sep, eq, name) {
  3924 + sep = sep || '&';
  3925 + eq = eq || '=';
  3926 + if (obj === null) {
  3927 + obj = undefined;
  3928 + }
  3929 +
  3930 + if (typeof obj === 'object') {
  3931 + return map(objectKeys(obj), function(k) {
  3932 + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
  3933 + if (isArray(obj[k])) {
  3934 + return map(obj[k], function(v) {
  3935 + return ks + encodeURIComponent(stringifyPrimitive(v));
  3936 + }).join(sep);
  3937 + } else {
  3938 + return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
  3939 + }
  3940 + }).join(sep);
  3941 +
  3942 + }
  3943 +
  3944 + if (!name) return '';
  3945 + return encodeURIComponent(stringifyPrimitive(name)) + eq +
  3946 + encodeURIComponent(stringifyPrimitive(obj));
  3947 +};
  3948 +
  3949 +var isArray = Array.isArray || function (xs) {
  3950 + return Object.prototype.toString.call(xs) === '[object Array]';
  3951 +};
  3952 +
  3953 +function map (xs, f) {
  3954 + if (xs.map) return xs.map(f);
  3955 + var res = [];
  3956 + for (var i = 0; i < xs.length; i++) {
  3957 + res.push(f(xs[i], i));
  3958 + }
  3959 + return res;
  3960 +}
  3961 +
  3962 +var objectKeys = Object.keys || function (obj) {
  3963 + var res = [];
  3964 + for (var key in obj) {
  3965 + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
  3966 + }
  3967 + return res;
  3968 +};
  3969 +
  3970 +},{}],25:[function(require,module,exports){
  3971 +'use strict';
  3972 +
  3973 +exports.decode = exports.parse = require('./decode');
  3974 +exports.encode = exports.stringify = require('./encode');
  3975 +
  3976 +},{"./decode":23,"./encode":24}],26:[function(require,module,exports){
  3977 +// Copyright Joyent, Inc. and other Node contributors.
  3978 +//
  3979 +// Permission is hereby granted, free of charge, to any person obtaining a
  3980 +// copy of this software and associated documentation files (the
  3981 +// "Software"), to deal in the Software without restriction, including
  3982 +// without limitation the rights to use, copy, modify, merge, publish,
  3983 +// distribute, sublicense, and/or sell copies of the Software, and to permit
  3984 +// persons to whom the Software is furnished to do so, subject to the
  3985 +// following conditions:
  3986 +//
  3987 +// The above copyright notice and this permission notice shall be included
  3988 +// in all copies or substantial portions of the Software.
  3989 +//
  3990 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  3991 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  3992 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  3993 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  3994 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  3995 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  3996 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
  3997 +
  3998 +var punycode = require('punycode');
  3999 +
  4000 +exports.parse = urlParse;
  4001 +exports.resolve = urlResolve;
  4002 +exports.resolveObject = urlResolveObject;
  4003 +exports.format = urlFormat;
  4004 +
  4005 +exports.Url = Url;
  4006 +
  4007 +function Url() {
  4008 + this.protocol = null;
  4009 + this.slashes = null;
  4010 + this.auth = null;
  4011 + this.host = null;
  4012 + this.port = null;
  4013 + this.hostname = null;
  4014 + this.hash = null;
  4015 + this.search = null;
  4016 + this.query = null;
  4017 + this.pathname = null;
  4018 + this.path = null;
  4019 + this.href = null;
  4020 +}
  4021 +
  4022 +// Reference: RFC 3986, RFC 1808, RFC 2396
  4023 +
  4024 +// define these here so at least they only have to be
  4025 +// compiled once on the first module load.
  4026 +var protocolPattern = /^([a-z0-9.+-]+:)/i,
  4027 + portPattern = /:[0-9]*$/,
  4028 +
  4029 + // RFC 2396: characters reserved for delimiting URLs.
  4030 + // We actually just auto-escape these.
  4031 + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  4032 +
  4033 + // RFC 2396: characters not allowed for various reasons.
  4034 + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  4035 +
  4036 + // Allowed by RFCs, but cause of XSS attacks. Always escape these.
  4037 + autoEscape = ['\''].concat(unwise),
  4038 + // Characters that are never ever allowed in a hostname.
  4039 + // Note that any invalid chars are also handled, but these
  4040 + // are the ones that are *expected* to be seen, so we fast-path
  4041 + // them.
  4042 + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
  4043 + hostEndingChars = ['/', '?', '#'],
  4044 + hostnameMaxLen = 255,
  4045 + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
  4046 + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
  4047 + // protocols that can allow "unsafe" and "unwise" chars.
  4048 + unsafeProtocol = {
  4049 + 'javascript': true,
  4050 + 'javascript:': true
  4051 + },
  4052 + // protocols that never have a hostname.
  4053 + hostlessProtocol = {
  4054 + 'javascript': true,
  4055 + 'javascript:': true
  4056 + },
  4057 + // protocols that always contain a // bit.
  4058 + slashedProtocol = {
  4059 + 'http': true,
  4060 + 'https': true,
  4061 + 'ftp': true,
  4062 + 'gopher': true,
  4063 + 'file': true,
  4064 + 'http:': true,
  4065 + 'https:': true,
  4066 + 'ftp:': true,
  4067 + 'gopher:': true,
  4068 + 'file:': true
  4069 + },
  4070 + querystring = require('querystring');
  4071 +
  4072 +function urlParse(url, parseQueryString, slashesDenoteHost) {
  4073 + if (url && isObject(url) && url instanceof Url) return url;
  4074 +
  4075 + var u = new Url;
  4076 + u.parse(url, parseQueryString, slashesDenoteHost);
  4077 + return u;
  4078 +}
  4079 +
  4080 +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
  4081 + if (!isString(url)) {
  4082 + throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
  4083 + }
  4084 +
  4085 + var rest = url;
  4086 +
  4087 + // trim before proceeding.
  4088 + // This is to support parse stuff like " http://foo.com \n"
  4089 + rest = rest.trim();
  4090 +
  4091 + var proto = protocolPattern.exec(rest);
  4092 + if (proto) {
  4093 + proto = proto[0];
  4094 + var lowerProto = proto.toLowerCase();
  4095 + this.protocol = lowerProto;
  4096 + rest = rest.substr(proto.length);
  4097 + }
  4098 +
  4099 + // figure out if it's got a host
  4100 + // user@server is *always* interpreted as a hostname, and url
  4101 + // resolution will treat //foo/bar as host=foo,path=bar because that's
  4102 + // how the browser resolves relative URLs.
  4103 + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
  4104 + var slashes = rest.substr(0, 2) === '//';
  4105 + if (slashes && !(proto && hostlessProtocol[proto])) {
  4106 + rest = rest.substr(2);
  4107 + this.slashes = true;
  4108 + }
  4109 + }
  4110 +
  4111 + if (!hostlessProtocol[proto] &&
  4112 + (slashes || (proto && !slashedProtocol[proto]))) {
  4113 +
  4114 + // there's a hostname.
  4115 + // the first instance of /, ?, ;, or # ends the host.
  4116 + //
  4117 + // If there is an @ in the hostname, then non-host chars *are* allowed
  4118 + // to the left of the last @ sign, unless some host-ending character
  4119 + // comes *before* the @-sign.
  4120 + // URLs are obnoxious.
  4121 + //
  4122 + // ex:
  4123 + // http://a@b@c/ => user:a@b host:c
  4124 + // http://a@b?@c => user:a host:c path:/?@c
  4125 +
  4126 + // v0.12 TODO(isaacs): This is not quite how Chrome does things.
  4127 + // Review our test case against browsers more comprehensively.
  4128 +
  4129 + // find the first instance of any hostEndingChars
  4130 + var hostEnd = -1;
  4131 + for (var i = 0; i < hostEndingChars.length; i++) {
  4132 + var hec = rest.indexOf(hostEndingChars[i]);
  4133 + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
  4134 + hostEnd = hec;
  4135 + }
  4136 +
  4137 + // at this point, either we have an explicit point where the
  4138 + // auth portion cannot go past, or the last @ char is the decider.
  4139 + var auth, atSign;
  4140 + if (hostEnd === -1) {
  4141 + // atSign can be anywhere.
  4142 + atSign = rest.lastIndexOf('@');
  4143 + } else {
  4144 + // atSign must be in auth portion.
  4145 + // http://a@b/c@d => host:b auth:a path:/c@d
  4146 + atSign = rest.lastIndexOf('@', hostEnd);
  4147 + }
  4148 +
  4149 + // Now we have a portion which is definitely the auth.
  4150 + // Pull that off.
  4151 + if (atSign !== -1) {
  4152 + auth = rest.slice(0, atSign);
  4153 + rest = rest.slice(atSign + 1);
  4154 + this.auth = decodeURIComponent(auth);
  4155 + }
  4156 +
  4157 + // the host is the remaining to the left of the first non-host char
  4158 + hostEnd = -1;
  4159 + for (var i = 0; i < nonHostChars.length; i++) {
  4160 + var hec = rest.indexOf(nonHostChars[i]);
  4161 + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
  4162 + hostEnd = hec;
  4163 + }
  4164 + // if we still have not hit it, then the entire thing is a host.
  4165 + if (hostEnd === -1)
  4166 + hostEnd = rest.length;
  4167 +
  4168 + this.host = rest.slice(0, hostEnd);
  4169 + rest = rest.slice(hostEnd);
  4170 +
  4171 + // pull out port.
  4172 + this.parseHost();
  4173 +
  4174 + // we've indicated that there is a hostname,
  4175 + // so even if it's empty, it has to be present.
  4176 + this.hostname = this.hostname || '';
  4177 +
  4178 + // if hostname begins with [ and ends with ]
  4179 + // assume that it's an IPv6 address.
  4180 + var ipv6Hostname = this.hostname[0] === '[' &&
  4181 + this.hostname[this.hostname.length - 1] === ']';
  4182 +
  4183 + // validate a little.
  4184 + if (!ipv6Hostname) {
  4185 + var hostparts = this.hostname.split(/\./);
  4186 + for (var i = 0, l = hostparts.length; i < l; i++) {
  4187 + var part = hostparts[i];
  4188 + if (!part) continue;
  4189 + if (!part.match(hostnamePartPattern)) {
  4190 + var newpart = '';
  4191 + for (var j = 0, k = part.length; j < k; j++) {
  4192 + if (part.charCodeAt(j) > 127) {
  4193 + // we replace non-ASCII char with a temporary placeholder
  4194 + // we need this to make sure size of hostname is not
  4195 + // broken by replacing non-ASCII by nothing
  4196 + newpart += 'x';
  4197 + } else {
  4198 + newpart += part[j];
  4199 + }
  4200 + }
  4201 + // we test again with ASCII char only
  4202 + if (!newpart.match(hostnamePartPattern)) {
  4203 + var validParts = hostparts.slice(0, i);
  4204 + var notHost = hostparts.slice(i + 1);
  4205 + var bit = part.match(hostnamePartStart);
  4206 + if (bit) {
  4207 + validParts.push(bit[1]);
  4208 + notHost.unshift(bit[2]);
  4209 + }
  4210 + if (notHost.length) {
  4211 + rest = '/' + notHost.join('.') + rest;
  4212 + }
  4213 + this.hostname = validParts.join('.');
  4214 + break;
  4215 + }
  4216 + }
  4217 + }
  4218 + }
  4219 +
  4220 + if (this.hostname.length > hostnameMaxLen) {
  4221 + this.hostname = '';
  4222 + } else {
  4223 + // hostnames are always lower case.
  4224 + this.hostname = this.hostname.toLowerCase();
  4225 + }
  4226 +
  4227 + if (!ipv6Hostname) {
  4228 + // IDNA Support: Returns a puny coded representation of "domain".
  4229 + // It only converts the part of the domain name that
  4230 + // has non ASCII characters. I.e. it dosent matter if
  4231 + // you call it with a domain that already is in ASCII.
  4232 + var domainArray = this.hostname.split('.');
  4233 + var newOut = [];
  4234 + for (var i = 0; i < domainArray.length; ++i) {
  4235 + var s = domainArray[i];
  4236 + newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
  4237 + 'xn--' + punycode.encode(s) : s);
  4238 + }
  4239 + this.hostname = newOut.join('.');
  4240 + }
  4241 +
  4242 + var p = this.port ? ':' + this.port : '';
  4243 + var h = this.hostname || '';
  4244 + this.host = h + p;
  4245 + this.href += this.host;
  4246 +
  4247 + // strip [ and ] from the hostname
  4248 + // the host field still retains them, though
  4249 + if (ipv6Hostname) {
  4250 + this.hostname = this.hostname.substr(1, this.hostname.length - 2);
  4251 + if (rest[0] !== '/') {
  4252 + rest = '/' + rest;
  4253 + }
  4254 + }
  4255 + }
  4256 +
  4257 + // now rest is set to the post-host stuff.
  4258 + // chop off any delim chars.
  4259 + if (!unsafeProtocol[lowerProto]) {
  4260 +
  4261 + // First, make 100% sure that any "autoEscape" chars get
  4262 + // escaped, even if encodeURIComponent doesn't think they
  4263 + // need to be.
  4264 + for (var i = 0, l = autoEscape.length; i < l; i++) {
  4265 + var ae = autoEscape[i];
  4266 + var esc = encodeURIComponent(ae);
  4267 + if (esc === ae) {
  4268 + esc = escape(ae);
  4269 + }
  4270 + rest = rest.split(ae).join(esc);
  4271 + }
  4272 + }
  4273 +
  4274 +
  4275 + // chop off from the tail first.
  4276 + var hash = rest.indexOf('#');
  4277 + if (hash !== -1) {
  4278 + // got a fragment string.
  4279 + this.hash = rest.substr(hash);
  4280 + rest = rest.slice(0, hash);
  4281 + }
  4282 + var qm = rest.indexOf('?');
  4283 + if (qm !== -1) {
  4284 + this.search = rest.substr(qm);
  4285 + this.query = rest.substr(qm + 1);
  4286 + if (parseQueryString) {
  4287 + this.query = querystring.parse(this.query);
  4288 + }
  4289 + rest = rest.slice(0, qm);
  4290 + } else if (parseQueryString) {
  4291 + // no query string, but parseQueryString still requested
  4292 + this.search = '';
  4293 + this.query = {};
  4294 + }
  4295 + if (rest) this.pathname = rest;
  4296 + if (slashedProtocol[lowerProto] &&
  4297 + this.hostname && !this.pathname) {
  4298 + this.pathname = '/';
  4299 + }
  4300 +
  4301 + //to support http.request
  4302 + if (this.pathname || this.search) {
  4303 + var p = this.pathname || '';
  4304 + var s = this.search || '';
  4305 + this.path = p + s;
  4306 + }
  4307 +
  4308 + // finally, reconstruct the href based on what has been validated.
  4309 + this.href = this.format();
  4310 + return this;
  4311 +};
  4312 +
  4313 +// format a parsed object into a url string
  4314 +function urlFormat(obj) {
  4315 + // ensure it's an object, and not a string url.
  4316 + // If it's an obj, this is a no-op.
  4317 + // this way, you can call url_format() on strings
  4318 + // to clean up potentially wonky urls.
  4319 + if (isString(obj)) obj = urlParse(obj);
  4320 + if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
  4321 + return obj.format();
  4322 +}
  4323 +
  4324 +Url.prototype.format = function() {
  4325 + var auth = this.auth || '';
  4326 + if (auth) {
  4327 + auth = encodeURIComponent(auth);
  4328 + auth = auth.replace(/%3A/i, ':');
  4329 + auth += '@';
  4330 + }
  4331 +
  4332 + var protocol = this.protocol || '',
  4333 + pathname = this.pathname || '',
  4334 + hash = this.hash || '',
  4335 + host = false,
  4336 + query = '';
  4337 +
  4338 + if (this.host) {
  4339 + host = auth + this.host;
  4340 + } else if (this.hostname) {
  4341 + host = auth + (this.hostname.indexOf(':') === -1 ?
  4342 + this.hostname :
  4343 + '[' + this.hostname + ']');
  4344 + if (this.port) {
  4345 + host += ':' + this.port;
  4346 + }
  4347 + }
  4348 +
  4349 + if (this.query &&
  4350 + isObject(this.query) &&
  4351 + Object.keys(this.query).length) {
  4352 + query = querystring.stringify(this.query);
  4353 + }
  4354 +
  4355 + var search = this.search || (query && ('?' + query)) || '';
  4356 +
  4357 + if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  4358 +
  4359 + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
  4360 + // unless they had them to begin with.
  4361 + if (this.slashes ||
  4362 + (!protocol || slashedProtocol[protocol]) && host !== false) {
  4363 + host = '//' + (host || '');
  4364 + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
  4365 + } else if (!host) {
  4366 + host = '';
  4367 + }
  4368 +
  4369 + if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
  4370 + if (search && search.charAt(0) !== '?') search = '?' + search;
  4371 +
  4372 + pathname = pathname.replace(/[?#]/g, function(match) {
  4373 + return encodeURIComponent(match);
  4374 + });
  4375 + search = search.replace('#', '%23');
  4376 +
  4377 + return protocol + host + pathname + search + hash;
  4378 +};
  4379 +
  4380 +function urlResolve(source, relative) {
  4381 + return urlParse(source, false, true).resolve(relative);
  4382 +}
  4383 +
  4384 +Url.prototype.resolve = function(relative) {
  4385 + return this.resolveObject(urlParse(relative, false, true)).format();
  4386 +};
  4387 +
  4388 +function urlResolveObject(source, relative) {
  4389 + if (!source) return relative;
  4390 + return urlParse(source, false, true).resolveObject(relative);
  4391 +}
  4392 +
  4393 +Url.prototype.resolveObject = function(relative) {
  4394 + if (isString(relative)) {
  4395 + var rel = new Url();
  4396 + rel.parse(relative, false, true);
  4397 + relative = rel;
  4398 + }
  4399 +
  4400 + var result = new Url();
  4401 + Object.keys(this).forEach(function(k) {
  4402 + result[k] = this[k];
  4403 + }, this);
  4404 +
  4405 + // hash is always overridden, no matter what.
  4406 + // even href="" will remove it.
  4407 + result.hash = relative.hash;
  4408 +
  4409 + // if the relative url is empty, then there's nothing left to do here.
  4410 + if (relative.href === '') {
  4411 + result.href = result.format();
  4412 + return result;
  4413 + }
  4414 +
  4415 + // hrefs like //foo/bar always cut to the protocol.
  4416 + if (relative.slashes && !relative.protocol) {
  4417 + // take everything except the protocol from relative
  4418 + Object.keys(relative).forEach(function(k) {
  4419 + if (k !== 'protocol')
  4420 + result[k] = relative[k];
  4421 + });
  4422 +
  4423 + //urlParse appends trailing / to urls like http://www.example.com
  4424 + if (slashedProtocol[result.protocol] &&
  4425 + result.hostname && !result.pathname) {
  4426 + result.path = result.pathname = '/';
  4427 + }
  4428 +
  4429 + result.href = result.format();
  4430 + return result;
  4431 + }
  4432 +
  4433 + if (relative.protocol && relative.protocol !== result.protocol) {
  4434 + // if it's a known url protocol, then changing
  4435 + // the protocol does weird things
  4436 + // first, if it's not file:, then we MUST have a host,
  4437 + // and if there was a path
  4438 + // to begin with, then we MUST have a path.
  4439 + // if it is file:, then the host is dropped,
  4440 + // because that's known to be hostless.
  4441 + // anything else is assumed to be absolute.
  4442 + if (!slashedProtocol[relative.protocol]) {
  4443 + Object.keys(relative).forEach(function(k) {
  4444 + result[k] = relative[k];
  4445 + });
  4446 + result.href = result.format();
  4447 + return result;
  4448 + }
  4449 +
  4450 + result.protocol = relative.protocol;
  4451 + if (!relative.host && !hostlessProtocol[relative.protocol]) {
  4452 + var relPath = (relative.pathname || '').split('/');
  4453 + while (relPath.length && !(relative.host = relPath.shift()));
  4454 + if (!relative.host) relative.host = '';
  4455 + if (!relative.hostname) relative.hostname = '';
  4456 + if (relPath[0] !== '') relPath.unshift('');
  4457 + if (relPath.length < 2) relPath.unshift('');
  4458 + result.pathname = relPath.join('/');
  4459 + } else {
  4460 + result.pathname = relative.pathname;
  4461 + }
  4462 + result.search = relative.search;
  4463 + result.query = relative.query;
  4464 + result.host = relative.host || '';
  4465 + result.auth = relative.auth;
  4466 + result.hostname = relative.hostname || relative.host;
  4467 + result.port = relative.port;
  4468 + // to support http.request
  4469 + if (result.pathname || result.search) {
  4470 + var p = result.pathname || '';
  4471 + var s = result.search || '';
  4472 + result.path = p + s;
  4473 + }
  4474 + result.slashes = result.slashes || relative.slashes;
  4475 + result.href = result.format();
  4476 + return result;
  4477 + }
  4478 +
  4479 + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
  4480 + isRelAbs = (
  4481 + relative.host ||
  4482 + relative.pathname && relative.pathname.charAt(0) === '/'
  4483 + ),
  4484 + mustEndAbs = (isRelAbs || isSourceAbs ||
  4485 + (result.host && relative.pathname)),
  4486 + removeAllDots = mustEndAbs,
  4487 + srcPath = result.pathname && result.pathname.split('/') || [],
  4488 + relPath = relative.pathname && relative.pathname.split('/') || [],
  4489 + psychotic = result.protocol && !slashedProtocol[result.protocol];
  4490 +
  4491 + // if the url is a non-slashed url, then relative
  4492 + // links like ../.. should be able
  4493 + // to crawl up to the hostname, as well. This is strange.
  4494 + // result.protocol has already been set by now.
  4495 + // Later on, put the first path part into the host field.
  4496 + if (psychotic) {
  4497 + result.hostname = '';
  4498 + result.port = null;
  4499 + if (result.host) {
  4500 + if (srcPath[0] === '') srcPath[0] = result.host;
  4501 + else srcPath.unshift(result.host);
  4502 + }
  4503 + result.host = '';
  4504 + if (relative.protocol) {
  4505 + relative.hostname = null;
  4506 + relative.port = null;
  4507 + if (relative.host) {
  4508 + if (relPath[0] === '') relPath[0] = relative.host;
  4509 + else relPath.unshift(relative.host);
  4510 + }
  4511 + relative.host = null;
  4512 + }
  4513 + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
  4514 + }
  4515 +
  4516 + if (isRelAbs) {
  4517 + // it's absolute.
  4518 + result.host = (relative.host || relative.host === '') ?
  4519 + relative.host : result.host;
  4520 + result.hostname = (relative.hostname || relative.hostname === '') ?
  4521 + relative.hostname : result.hostname;
  4522 + result.search = relative.search;
  4523 + result.query = relative.query;
  4524 + srcPath = relPath;
  4525 + // fall through to the dot-handling below.
  4526 + } else if (relPath.length) {
  4527 + // it's relative
  4528 + // throw away the existing file, and take the new path instead.
  4529 + if (!srcPath) srcPath = [];
  4530 + srcPath.pop();
  4531 + srcPath = srcPath.concat(relPath);
  4532 + result.search = relative.search;
  4533 + result.query = relative.query;
  4534 + } else if (!isNullOrUndefined(relative.search)) {
  4535 + // just pull out the search.
  4536 + // like href='?foo'.
  4537 + // Put this after the other two cases because it simplifies the booleans
  4538 + if (psychotic) {
  4539 + result.hostname = result.host = srcPath.shift();
  4540 + //occationaly the auth can get stuck only in host
  4541 + //this especialy happens in cases like
  4542 + //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  4543 + var authInHost = result.host && result.host.indexOf('@') > 0 ?
  4544 + result.host.split('@') : false;
  4545 + if (authInHost) {
  4546 + result.auth = authInHost.shift();
  4547 + result.host = result.hostname = authInHost.shift();
  4548 + }
  4549 + }
  4550 + result.search = relative.search;
  4551 + result.query = relative.query;
  4552 + //to support http.request
  4553 + if (!isNull(result.pathname) || !isNull(result.search)) {
  4554 + result.path = (result.pathname ? result.pathname : '') +
  4555 + (result.search ? result.search : '');
  4556 + }
  4557 + result.href = result.format();
  4558 + return result;
  4559 + }
  4560 +
  4561 + if (!srcPath.length) {
  4562 + // no path at all. easy.
  4563 + // we've already handled the other stuff above.
  4564 + result.pathname = null;
  4565 + //to support http.request
  4566 + if (result.search) {
  4567 + result.path = '/' + result.search;
  4568 + } else {
  4569 + result.path = null;
  4570 + }
  4571 + result.href = result.format();
  4572 + return result;
  4573 + }
  4574 +
  4575 + // if a url ENDs in . or .., then it must get a trailing slash.
  4576 + // however, if it ends in anything else non-slashy,
  4577 + // then it must NOT get a trailing slash.
  4578 + var last = srcPath.slice(-1)[0];
  4579 + var hasTrailingSlash = (
  4580 + (result.host || relative.host) && (last === '.' || last === '..') ||
  4581 + last === '');
  4582 +
  4583 + // strip single dots, resolve double dots to parent dir
  4584 + // if the path tries to go above the root, `up` ends up > 0
  4585 + var up = 0;
  4586 + for (var i = srcPath.length; i >= 0; i--) {
  4587 + last = srcPath[i];
  4588 + if (last == '.') {
  4589 + srcPath.splice(i, 1);
  4590 + } else if (last === '..') {
  4591 + srcPath.splice(i, 1);
  4592 + up++;
  4593 + } else if (up) {
  4594 + srcPath.splice(i, 1);
  4595 + up--;
  4596 + }
  4597 + }
  4598 +
  4599 + // if the path is allowed to go above the root, restore leading ..s
  4600 + if (!mustEndAbs && !removeAllDots) {
  4601 + for (; up--; up) {
  4602 + srcPath.unshift('..');
  4603 + }
  4604 + }
  4605 +
  4606 + if (mustEndAbs && srcPath[0] !== '' &&
  4607 + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
  4608 + srcPath.unshift('');
  4609 + }
  4610 +
  4611 + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
  4612 + srcPath.push('');
  4613 + }
  4614 +
  4615 + var isAbsolute = srcPath[0] === '' ||
  4616 + (srcPath[0] && srcPath[0].charAt(0) === '/');
  4617 +
  4618 + // put the host back
  4619 + if (psychotic) {
  4620 + result.hostname = result.host = isAbsolute ? '' :
  4621 + srcPath.length ? srcPath.shift() : '';
  4622 + //occationaly the auth can get stuck only in host
  4623 + //this especialy happens in cases like
  4624 + //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
  4625 + var authInHost = result.host && result.host.indexOf('@') > 0 ?
  4626 + result.host.split('@') : false;
  4627 + if (authInHost) {
  4628 + result.auth = authInHost.shift();
  4629 + result.host = result.hostname = authInHost.shift();
  4630 + }
  4631 + }
  4632 +
  4633 + mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  4634 +
  4635 + if (mustEndAbs && !isAbsolute) {
  4636 + srcPath.unshift('');
  4637 + }
  4638 +
  4639 + if (!srcPath.length) {
  4640 + result.pathname = null;
  4641 + result.path = null;
  4642 + } else {
  4643 + result.pathname = srcPath.join('/');
  4644 + }
  4645 +
  4646 + //to support request.http
  4647 + if (!isNull(result.pathname) || !isNull(result.search)) {
  4648 + result.path = (result.pathname ? result.pathname : '') +
  4649 + (result.search ? result.search : '');
  4650 + }
  4651 + result.auth = relative.auth || result.auth;
  4652 + result.slashes = result.slashes || relative.slashes;
  4653 + result.href = result.format();
  4654 + return result;
  4655 +};
  4656 +
  4657 +Url.prototype.parseHost = function() {
  4658 + var host = this.host;
  4659 + var port = portPattern.exec(host);
  4660 + if (port) {
  4661 + port = port[0];
  4662 + if (port !== ':') {
  4663 + this.port = port.substr(1);
  4664 + }
  4665 + host = host.substr(0, host.length - port.length);
  4666 + }
  4667 + if (host) this.hostname = host;
  4668 +};
  4669 +
  4670 +function isString(arg) {
  4671 + return typeof arg === "string";
  4672 +}
  4673 +
  4674 +function isObject(arg) {
  4675 + return typeof arg === 'object' && arg !== null;
  4676 +}
  4677 +
  4678 +function isNull(arg) {
  4679 + return arg === null;
  4680 +}
  4681 +function isNullOrUndefined(arg) {
  4682 + return arg == null;
  4683 +}
  4684 +
  4685 +},{"punycode":22,"querystring":25}],27:[function(require,module,exports){
  4686 +module.exports = function isBuffer(arg) {
  4687 + return arg && typeof arg === 'object'
  4688 + && typeof arg.copy === 'function'
  4689 + && typeof arg.fill === 'function'
  4690 + && typeof arg.readUInt8 === 'function';
  4691 +}
  4692 +},{}],28:[function(require,module,exports){
  4693 +(function (process,global){
  4694 +// Copyright Joyent, Inc. and other Node contributors.
  4695 +//
  4696 +// Permission is hereby granted, free of charge, to any person obtaining a
  4697 +// copy of this software and associated documentation files (the
  4698 +// "Software"), to deal in the Software without restriction, including
  4699 +// without limitation the rights to use, copy, modify, merge, publish,
  4700 +// distribute, sublicense, and/or sell copies of the Software, and to permit
  4701 +// persons to whom the Software is furnished to do so, subject to the
  4702 +// following conditions:
  4703 +//
  4704 +// The above copyright notice and this permission notice shall be included
  4705 +// in all copies or substantial portions of the Software.
  4706 +//
  4707 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  4708 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  4709 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  4710 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  4711 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  4712 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  4713 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
  4714 +
  4715 +var formatRegExp = /%[sdj%]/g;
  4716 +exports.format = function(f) {
  4717 + if (!isString(f)) {
  4718 + var objects = [];
  4719 + for (var i = 0; i < arguments.length; i++) {
  4720 + objects.push(inspect(arguments[i]));
  4721 + }
  4722 + return objects.join(' ');
  4723 + }
  4724 +
  4725 + var i = 1;
  4726 + var args = arguments;
  4727 + var len = args.length;
  4728 + var str = String(f).replace(formatRegExp, function(x) {
  4729 + if (x === '%%') return '%';
  4730 + if (i >= len) return x;
  4731 + switch (x) {
  4732 + case '%s': return String(args[i++]);
  4733 + case '%d': return Number(args[i++]);
  4734 + case '%j':
  4735 + try {
  4736 + return JSON.stringify(args[i++]);
  4737 + } catch (_) {
  4738 + return '[Circular]';
  4739 + }
  4740 + default:
  4741 + return x;
  4742 + }
  4743 + });
  4744 + for (var x = args[i]; i < len; x = args[++i]) {
  4745 + if (isNull(x) || !isObject(x)) {
  4746 + str += ' ' + x;
  4747 + } else {
  4748 + str += ' ' + inspect(x);
  4749 + }
  4750 + }
  4751 + return str;
  4752 +};
  4753 +
  4754 +
  4755 +// Mark that a method should not be used.
  4756 +// Returns a modified function which warns once by default.
  4757 +// If --no-deprecation is set, then it is a no-op.
  4758 +exports.deprecate = function(fn, msg) {
  4759 + // Allow for deprecating things in the process of starting up.
  4760 + if (isUndefined(global.process)) {
  4761 + return function() {
  4762 + return exports.deprecate(fn, msg).apply(this, arguments);
  4763 + };
  4764 + }
  4765 +
  4766 + if (process.noDeprecation === true) {
  4767 + return fn;
  4768 + }
  4769 +
  4770 + var warned = false;
  4771 + function deprecated() {
  4772 + if (!warned) {
  4773 + if (process.throwDeprecation) {
  4774 + throw new Error(msg);
  4775 + } else if (process.traceDeprecation) {
  4776 + console.trace(msg);
  4777 + } else {
  4778 + console.error(msg);
  4779 + }
  4780 + warned = true;
  4781 + }
  4782 + return fn.apply(this, arguments);
  4783 + }
  4784 +
  4785 + return deprecated;
  4786 +};
  4787 +
  4788 +
  4789 +var debugs = {};
  4790 +var debugEnviron;
  4791 +exports.debuglog = function(set) {
  4792 + if (isUndefined(debugEnviron))
  4793 + debugEnviron = process.env.NODE_DEBUG || '';
  4794 + set = set.toUpperCase();
  4795 + if (!debugs[set]) {
  4796 + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
  4797 + var pid = process.pid;
  4798 + debugs[set] = function() {
  4799 + var msg = exports.format.apply(exports, arguments);
  4800 + console.error('%s %d: %s', set, pid, msg);
  4801 + };
  4802 + } else {
  4803 + debugs[set] = function() {};
  4804 + }
  4805 + }
  4806 + return debugs[set];
  4807 +};
  4808 +
  4809 +
  4810 +/**
  4811 + * Echos the value of a value. Trys to print the value out
  4812 + * in the best way possible given the different types.
  4813 + *
  4814 + * @param {Object} obj The object to print out.
  4815 + * @param {Object} opts Optional options object that alters the output.
  4816 + */
  4817 +/* legacy: obj, showHidden, depth, colors*/
  4818 +function inspect(obj, opts) {
  4819 + // default options
  4820 + var ctx = {
  4821 + seen: [],
  4822 + stylize: stylizeNoColor
  4823 + };
  4824 + // legacy...
  4825 + if (arguments.length >= 3) ctx.depth = arguments[2];
  4826 + if (arguments.length >= 4) ctx.colors = arguments[3];
  4827 + if (isBoolean(opts)) {
  4828 + // legacy...
  4829 + ctx.showHidden = opts;
  4830 + } else if (opts) {
  4831 + // got an "options" object
  4832 + exports._extend(ctx, opts);
  4833 + }
  4834 + // set default options
  4835 + if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
  4836 + if (isUndefined(ctx.depth)) ctx.depth = 2;
  4837 + if (isUndefined(ctx.colors)) ctx.colors = false;
  4838 + if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
  4839 + if (ctx.colors) ctx.stylize = stylizeWithColor;
  4840 + return formatValue(ctx, obj, ctx.depth);
  4841 +}
  4842 +exports.inspect = inspect;
  4843 +
  4844 +
  4845 +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  4846 +inspect.colors = {
  4847 + 'bold' : [1, 22],
  4848 + 'italic' : [3, 23],
  4849 + 'underline' : [4, 24],
  4850 + 'inverse' : [7, 27],
  4851 + 'white' : [37, 39],
  4852 + 'grey' : [90, 39],
  4853 + 'black' : [30, 39],
  4854 + 'blue' : [34, 39],
  4855 + 'cyan' : [36, 39],
  4856 + 'green' : [32, 39],
  4857 + 'magenta' : [35, 39],
  4858 + 'red' : [31, 39],
  4859 + 'yellow' : [33, 39]
  4860 +};
  4861 +
  4862 +// Don't use 'blue' not visible on cmd.exe
  4863 +inspect.styles = {
  4864 + 'special': 'cyan',
  4865 + 'number': 'yellow',
  4866 + 'boolean': 'yellow',
  4867 + 'undefined': 'grey',
  4868 + 'null': 'bold',
  4869 + 'string': 'green',
  4870 + 'date': 'magenta',
  4871 + // "name": intentionally not styling
  4872 + 'regexp': 'red'
  4873 +};
  4874 +
  4875 +
  4876 +function stylizeWithColor(str, styleType) {
  4877 + var style = inspect.styles[styleType];
  4878 +
  4879 + if (style) {
  4880 + return '\u001b[' + inspect.colors[style][0] + 'm' + str +
  4881 + '\u001b[' + inspect.colors[style][1] + 'm';
  4882 + } else {
  4883 + return str;
  4884 + }
  4885 +}
  4886 +
  4887 +
  4888 +function stylizeNoColor(str, styleType) {
  4889 + return str;
  4890 +}
  4891 +
  4892 +
  4893 +function arrayToHash(array) {
  4894 + var hash = {};
  4895 +
  4896 + array.forEach(function(val, idx) {
  4897 + hash[val] = true;
  4898 + });
  4899 +
  4900 + return hash;
  4901 +}
  4902