Commit 73bcce880ee4047fd34a459a3f17dd5341ad3e21
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
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
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
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
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.<ElementDescriptor></code> | |
28 | + * [.elementsByTagName](#hydrolysis.Analyzer#elementsByTagName) : <code>Object.<string, ElementDescriptor></code> | |
29 | + * [.features](#hydrolysis.Analyzer#features) : <code>Array.<FeatureDescriptor></code> | |
30 | + * [.behaviors](#hydrolysis.Analyzer#behaviors) : <code>Array.<BehaviorDescriptor></code> | |
31 | + * [.html](#hydrolysis.Analyzer#html) : <code>Object.<string, AnalyzedDocument></code> | |
32 | + * [.parsedDocuments](#hydrolysis.Analyzer#parsedDocuments) : <code>Object</code> | |
33 | + * [._getDependencies(href, [found], [transitive])](#hydrolysis.Analyzer#_getDependencies) โ <code>Array.<string></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.<Analyzer></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.<string></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.<ElementDescriptor></code> | |
68 | + * [.elementsByTagName](#hydrolysis.Analyzer#elementsByTagName) : <code>Object.<string, ElementDescriptor></code> | |
69 | + * [.features](#hydrolysis.Analyzer#features) : <code>Array.<FeatureDescriptor></code> | |
70 | + * [.behaviors](#hydrolysis.Analyzer#behaviors) : <code>Array.<BehaviorDescriptor></code> | |
71 | + * [.html](#hydrolysis.Analyzer#html) : <code>Object.<string, AnalyzedDocument></code> | |
72 | + * [.parsedDocuments](#hydrolysis.Analyzer#parsedDocuments) : <code>Object</code> | |
73 | + * [._getDependencies(href, [found], [transitive])](#hydrolysis.Analyzer#_getDependencies) โ <code>Array.<string></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.<Analyzer></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.<ElementDescriptor></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.<string, ElementDescriptor></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.<FeatureDescriptor></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.<BehaviorDescriptor></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.<string, AnalyzedDocument></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.<string></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.<string></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.<string, boolean></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.<Analyzer></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.<Analyzer></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.<string></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.<string></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.<string></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.<ElementDescriptor></code> | The elements from the document | | |
308 | +| features | <code>Array.<FeatureDescriptor></code> | The features from the document | | |
309 | +| behaviors | <code>Array.<FeatureDescriptor></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.<ParsedImport></code> | The parsed representation of the doc. Use the `ast` property to get the full `parse5` ast | | |
322 | +| depsLoaded | <code>Promise.<Array.<string>></code> | Resolves to the list of this Document's transitive import dependencies | | |
323 | +| depHrefs | <code>Array.<string></code> | The direct dependencies of the document. | | |
324 | +| metadataLoaded | <code>Promise.<DocumentDescriptor></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 |