OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Logic to validate that developers are correctly using Polymer constructs. | 5 /// Logic to validate that developers are correctly using Polymer constructs. |
6 /// This is mainly used to produce warnings for feedback in the editor. | 6 /// This is mainly used to produce warnings for feedback in the editor. |
7 library polymer.src.build.linter; | 7 library polymer.src.build.linter; |
8 | 8 |
9 import 'dart:async'; | 9 import 'dart:async'; |
10 | 10 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 return; | 207 return; |
208 } | 208 } |
209 | 209 |
210 var tagName = node.attributes['name']; | 210 var tagName = node.attributes['name']; |
211 var extendsTag = node.attributes['extends']; | 211 var extendsTag = node.attributes['extends']; |
212 | 212 |
213 if (tagName == null) { | 213 if (tagName == null) { |
214 _logger.error('Missing tag name of the custom element. Please include an ' | 214 _logger.error('Missing tag name of the custom element. Please include an ' |
215 'attribute like \'name="your-tag-name"\'.', | 215 'attribute like \'name="your-tag-name"\'.', |
216 span: node.sourceSpan); | 216 span: node.sourceSpan); |
217 } else if (!_isCustomTag(tagName)) { | 217 } else if (!isCustomTagName(tagName)) { |
218 _logger.error('Invalid name "$tagName". Custom element names must have ' | 218 _logger.error('Invalid name "$tagName". Custom element names must have ' |
219 'at least one dash and can\'t be any of the following names: ' | 219 'at least one dash and can\'t be any of the following names: ' |
220 '${_invalidTagNames.keys.join(", ")}.', | 220 '${invalidTagNames.keys.join(", ")}.', |
221 span: node.sourceSpan); | 221 span: node.sourceSpan); |
222 } | 222 } |
223 | 223 |
224 if (_elements[extendsTag] == null && _isCustomTag(extendsTag)) { | 224 if (_elements[extendsTag] == null && isCustomTagName(extendsTag)) { |
225 _logger.warning('custom element with name "$extendsTag" not found.', | 225 _logger.warning('custom element with name "$extendsTag" not found.', |
226 span: node.sourceSpan); | 226 span: node.sourceSpan); |
227 } | 227 } |
228 | 228 |
229 var attrs = node.attributes['attributes']; | 229 var attrs = node.attributes['attributes']; |
230 if (attrs != null) { | 230 if (attrs != null) { |
231 var attrsSpan = node.attributeSpans['attributes']; | 231 var attrsSpan = node.attributeSpans['attributes']; |
232 | 232 |
233 // names='a b c' or names='a,b,c' | 233 // names='a b c' or names='a,b,c' |
234 // record each name for publishing | 234 // record each name for publishing |
235 for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { | 235 for (var attr in attrs.split(ATTRIBUTES_REGEX)) { |
236 // remove excess ws | 236 if (!_validateCustomAttributeName(attr.trim(), attrsSpan)) break; |
237 attr = attr.trim(); | |
238 if (!_validateCustomAttributeName(attr, attrsSpan)) break; | |
239 } | 237 } |
240 } | 238 } |
241 | 239 |
242 var oldValue = _inPolymerElement; | 240 var oldValue = _inPolymerElement; |
243 _inPolymerElement = true; | 241 _inPolymerElement = true; |
244 super.visitElement(node); | 242 super.visitElement(node); |
245 _inPolymerElement = oldValue; | 243 _inPolymerElement = oldValue; |
246 } | 244 } |
247 | 245 |
248 /// Checks for multiple Dart script tags in the same page, which is invalid. | 246 /// Checks for multiple Dart script tags in the same page, which is invalid. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 node.attributes.forEach((name, value) { | 290 node.attributes.forEach((name, value) { |
293 if (name is String && name.startsWith('on')) { | 291 if (name is String && name.startsWith('on')) { |
294 _validateEventHandler(node, name, value); | 292 _validateEventHandler(node, name, value); |
295 } | 293 } |
296 }); | 294 }); |
297 | 295 |
298 // Validate uses of custom-tags | 296 // Validate uses of custom-tags |
299 var nodeTag = node.localName; | 297 var nodeTag = node.localName; |
300 var hasIsAttribute; | 298 var hasIsAttribute; |
301 var customTagName; | 299 var customTagName; |
302 if (_isCustomTag(nodeTag)) { | 300 if (isCustomTagName(nodeTag)) { |
303 // <fancy-button> | 301 // <fancy-button> |
304 customTagName = nodeTag; | 302 customTagName = nodeTag; |
305 hasIsAttribute = false; | 303 hasIsAttribute = false; |
306 } else { | 304 } else { |
307 // <button is="fancy-button"> | 305 // <button is="fancy-button"> |
308 customTagName = node.attributes['is']; | 306 customTagName = node.attributes['is']; |
309 hasIsAttribute = true; | 307 hasIsAttribute = true; |
310 } | 308 } |
311 | 309 |
312 if (customTagName == null || customTagName == 'polymer-element') return; | 310 if (customTagName == null || customTagName == 'polymer-element') return; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 378 |
381 if (value.contains('(')) { | 379 if (value.contains('(')) { |
382 _logger.warning('Invalid event handler body "$value". Declare a method ' | 380 _logger.warning('Invalid event handler body "$value". Declare a method ' |
383 'in your custom element "void handlerName(event, detail, target)" ' | 381 'in your custom element "void handlerName(event, detail, target)" ' |
384 'and use the form $name="handlerName".', | 382 'and use the form $name="handlerName".', |
385 span: node.attributeSpans[name]); | 383 span: node.attributeSpans[name]); |
386 } | 384 } |
387 } | 385 } |
388 } | 386 } |
389 | 387 |
390 | |
391 // These names have meaning in SVG or MathML, so they aren't allowed as custom | |
392 // tags. | |
393 var _invalidTagNames = const { | |
394 'annotation-xml': '', | |
395 'color-profile': '', | |
396 'font-face': '', | |
397 'font-face-src': '', | |
398 'font-face-uri': '', | |
399 'font-face-format': '', | |
400 'font-face-name': '', | |
401 'missing-glyph': '', | |
402 }; | |
403 | |
404 /// Returns true if this is a valid custom element name. See: | |
405 /// <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#df
n-custom-element-name> | |
406 bool _isCustomTag(String name) { | |
407 if (name == null || !name.contains('-')) return false; | |
408 return !_invalidTagNames.containsKey(name); | |
409 } | |
410 | |
411 const String USE_INIT_DART = | 388 const String USE_INIT_DART = |
412 'To run a polymer application, you need to call "initPolymer". You can ' | 389 'To run a polymer application, you need to call "initPolymer". You can ' |
413 'either include a generic script tag that does this for you:' | 390 'either include a generic script tag that does this for you:' |
414 '\'<script type="application/dart">export "package:polymer/init.dart";' | 391 '\'<script type="application/dart">export "package:polymer/init.dart";' |
415 '</script>\' or add your own script tag and call that function. ' | 392 '</script>\' or add your own script tag and call that function. ' |
416 'Make sure the script tag is placed after all HTML imports.'; | 393 'Make sure the script tag is placed after all HTML imports.'; |
417 | 394 |
418 const String BOOT_JS_DEPRECATED = | 395 const String BOOT_JS_DEPRECATED = |
419 '"boot.js" is now deprecated. Instead, you can initialize your polymer ' | 396 '"boot.js" is now deprecated. Instead, you can initialize your polymer ' |
420 'application by calling "initPolymer()" in your main. If you don\'t have a ' | 397 'application by calling "initPolymer()" in your main. If you don\'t have a ' |
421 'main, then you can include our generic main by adding the following ' | 398 'main, then you can include our generic main by adding the following ' |
422 'script tag to your page: \'<script type="application/dart">export ' | 399 'script tag to your page: \'<script type="application/dart">export ' |
423 '"package:polymer/init.dart";</script>\'. Additionally you need to ' | 400 '"package:polymer/init.dart";</script>\'. Additionally you need to ' |
424 'include: \'<script src="packages/browser/dart.js"></script>\' in the page ' | 401 'include: \'<script src="packages/browser/dart.js"></script>\' in the page ' |
425 'too. Make sure these script tags come after all HTML imports.'; | 402 'too. Make sure these script tags come after all HTML imports.'; |
OLD | NEW |