Index: tools/dom/scripts/css_code_generator.py |
diff --git a/tools/dom/scripts/css_code_generator.py b/tools/dom/scripts/css_code_generator.py |
index 11bf7bcbf63ab04d2a66e2c3307fbbbe35bcd465..18351ae6aad32ddbaa0fd5c0bd9ca7417b085b3d 100644 |
--- a/tools/dom/scripts/css_code_generator.py |
+++ b/tools/dom/scripts/css_code_generator.py |
@@ -1,28 +1,28 @@ |
-#!/usr/bin/python2.6 |
+#!/usr/bin/python |
# |
-# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
+# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
# for details. All rights reserved. Use of this source code is governed by a |
# BSD-style license that can be found in the LICENSE file. |
-"""Generates CSSStyleDeclaration from css property definitions defined in WebKit.""" |
+"""Generates CSSStyleDeclaration template file from css property definitions |
+defined in WebKit.""" |
import tempfile, os |
COMMENT_LINE_PREFIX = ' * ' |
-SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' |
-INPUT_URL = 'http://trac.webkit.org/export/latest/trunk/%s' % SOURCE_PATH |
-INTERFACE_FILE = '../../html/src/CSSStyleDeclaration.dart' |
-CLASS_FILE = '../../html/src/CSSStyleDeclarationWrappingImplementation.dart' |
- |
-def main(): |
- _, css_names_file = tempfile.mkstemp('.CSSPropertyNames.in') |
- try: |
- if os.system('wget %s -O %s' % (INPUT_URL, css_names_file)): |
- return 1 |
- generate_code(css_names_file) |
- print 'Successfully generated %s and %s' % (INTERFACE_FILE, CLASS_FILE) |
- finally: |
- os.remove(css_names_file) |
+# TODO(efortuna): Pull from DEPS so that we have latest css *in sync* with our |
+# Dartium. Then remove the checked in CSSPropertyNames.in. |
+SOURCE_PATH = 'CSSPropertyNames.in' |
+#SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' |
+TEMPLATE_FILE = '../templates/html/impl/impl_CSSStyleDeclaration.darttemplate' |
+ |
+# Supported annotations for any specific CSS properties. |
+annotated = { |
+ 'transition': '''@SupportedBrowser(SupportedBrowser.CHROME) |
+ @SupportedBrowser(SupportedBrowser.FIREFOX) |
+ @SupportedBrowser(SupportedBrowser.IE, '10') |
+ @SupportedBrowser(SupportedBrowser.SAFARI)''' |
+} |
def camelCaseName(name): |
"""Convert a CSS property name to a lowerCamelCase name.""" |
@@ -35,165 +35,196 @@ def camelCaseName(name): |
words.append(word) |
return ''.join(words) |
-def generate_code(input_path): |
- data = open(input_path).readlines() |
+def GenerateCssTemplateFile(): |
+ data = open(SOURCE_PATH).readlines() |
# filter CSSPropertyNames.in to only the properties |
+ # TODO(efortuna): do we also want CSSPropertyNames.in? |
data = [d[:-1] for d in data |
if len(d) > 1 |
and not d.startswith('#') |
and not d.startswith('//') |
and not '=' in d] |
- interface_file = open(INTERFACE_FILE, 'w') |
- class_file = open(CLASS_FILE, 'w') |
- |
- interface_file.write(""" |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-// WARNING: Do not edit. |
-// This file was generated by html/scripts/css_code_generator.py |
- |
-// Source of CSS properties: |
-// %s |
- |
-// TODO(jacobr): add versions that take numeric values in px, miliseconds, etc. |
- |
-interface CSSStyleDeclaration { |
- |
- String get cssText; |
- |
- void set cssText(String value); |
- |
- int get length; |
- |
- CSSRule get parentRule; |
- |
- CSSValue getPropertyCSSValue(String propertyName); |
- |
- String getPropertyPriority(String propertyName); |
- |
- String getPropertyShorthand(String propertyName); |
- |
- String getPropertyValue(String propertyName); |
- |
- bool isPropertyImplicit(String propertyName); |
- |
- String item(int index); |
- |
- String removeProperty(String propertyName); |
- |
- void setProperty(String propertyName, String value, [String priority]); |
- |
-""".lstrip() % SOURCE_PATH) |
- |
+ class_file = open(TEMPLATE_FILE, 'w') |
class_file.write(""" |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
-// WARNING: Do not edit. |
-// This file was generated by html/scripts/css_code_generator.py |
+// WARNING: DO NOT EDIT THIS TEMPLATE FILE. |
+// The template file was generated by scripts/css_code_generator.py |
// Source of CSS properties: |
// %s |
-// TODO(jacobr): add versions that take numeric values in px, miliseconds, etc. |
- |
-class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implements CSSStyleDeclaration { |
- static String _cachedBrowserPrefix; |
+part of $LIBRARYNAME; |
- CSSStyleDeclarationWrappingImplementation._wrap(ptr) : super._wrap(ptr) {} |
+$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with |
+ $(CLASSNAME)Base $IMPLEMENTS { |
+ factory $CLASSNAME() => new CssStyleDeclaration.css(''); |
- static String get _browserPrefix { |
- if (_cachedBrowserPrefix == null) { |
- if (_Device.isFirefox) { |
- _cachedBrowserPrefix = '-moz-'; |
- } else { |
- _cachedBrowserPrefix = '-webkit-'; |
- } |
- // TODO(jacobr): support IE 9.0 and Opera as well. |
- } |
- return _cachedBrowserPrefix; |
+ factory $CLASSNAME.css(String css) { |
+ final style = new Element.tag('div').style; |
+ style.cssText = css; |
+ return style; |
} |
- String get cssText { return _ptr.cssText; } |
- |
- void set cssText(String value) { _ptr.cssText = value; } |
- |
- int get length { return _ptr.length; } |
- |
- CSSRule get parentRule { return LevelDom.wrapCSSRule(_ptr.parentRule); } |
- |
- CSSValue getPropertyCSSValue(String propertyName) { |
- return LevelDom.wrapCSSValue(_ptr.getPropertyCSSValue(propertyName)); |
+ String getPropertyValue(String propertyName) { |
+ var propValue = _getPropertyValueHelper(propertyName); |
+ return propValue != null ? propValue : ''; |
} |
- String getPropertyPriority(String propertyName) { |
- return _ptr.getPropertyPriority(propertyName); |
+ String _getPropertyValueHelper(String propertyName) { |
+ if (_supportsProperty(_camelCase(propertyName))) { |
+ return _getPropertyValue(propertyName); |
+ } else { |
+ return _getPropertyValue(Device.cssPrefix + propertyName); |
+ } |
} |
- String getPropertyShorthand(String propertyName) { |
- return _ptr.getPropertyShorthand(propertyName); |
+ /** |
+ * Returns true if the provided *CSS* property name is supported on this |
+ * element. |
+ * |
+ * Please note the property name camelCase, not-hyphens. This |
+ * method returns true if the property is accessible via an unprefixed _or_ |
+ * prefixed property. |
+ */ |
+ bool supportsProperty(String propertyName) { |
+ return _supportsProperty(propertyName) || |
+ _supportsProperty(_camelCase(Device.cssPrefix + propertyName)); |
} |
- String getPropertyValue(String propertyName) { |
- return _ptr.getPropertyValue(propertyName); |
+ bool _supportsProperty(String propertyName) { |
+$if DART2JS |
+ return JS('bool', '# in #', propertyName, this); |
+$else |
+ // You can't just check the value of a property, because there is no way |
+ // to distinguish between property not being present in the browser and |
+ // not having a value at all. (Ultimately we'll want the native method to |
+ // return null if the property doesn't exist and empty string if it's |
+ // defined but just doesn't have a value. |
+ return _hasProperty(propertyName); |
+$endif |
+ } |
+$if DARTIUM |
+ |
+ bool _hasProperty(String propertyName) => |
+ _blink.BlinkCSSStyleDeclaration.$__propertyQuery___Callback(this, propertyName); |
+$endif |
+ |
+ @DomName('CSSStyleDeclaration.setProperty') |
+ void setProperty(String propertyName, String value, [String priority]) { |
+ if (_supportsProperty(_camelCase(propertyName))) { |
+ return _setPropertyHelper(propertyName, value, priority); |
+ } else { |
+ return _setPropertyHelper(Device.cssPrefix + propertyName, value, |
+ priority); |
+ } |
} |
- bool isPropertyImplicit(String propertyName) { |
- return _ptr.isPropertyImplicit(propertyName); |
+ String _camelCase(String hyphenated) { |
+ bool firstWord = true; |
+ return hyphenated.splitMapJoin('-', onMatch : (_) => '', |
+ onNonMatch : (String word) { |
+ if (word.length > 0) { |
+ if (firstWord) { |
+ firstWord = false; |
+ return word; |
+ } |
+ return word[0].toUpperCase() + word.substring(1); |
+ } |
+ return ''; |
+ }); |
} |
- String item(int index) { |
- return _ptr.item(index); |
+$if DART2JS |
+ void _setPropertyHelper(String propertyName, String value, [String priority]) { |
+ // try/catch for IE9 which throws on unsupported values. |
+ try { |
+ if (value == null) value = ''; |
+ if (priority == null) { |
+ priority = ''; |
+ } |
+ JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority); |
+ // Bug #2772, IE9 requires a poke to actually apply the value. |
+ if (JS('bool', '!!#.setAttribute', this)) { |
+ JS('void', '#.setAttribute(#, #)', this, propertyName, value); |
+ } |
+ } catch (e) {} |
} |
- String removeProperty(String propertyName) { |
- return _ptr.removeProperty(propertyName); |
+ /** |
+ * Checks to see if CSS Transitions are supported. |
+ */ |
+ static bool get supportsTransitions { |
+ return supportsProperty('transition'); |
+ } |
+$else |
+ void _setPropertyHelper(String propertyName, String value, [String priority]) { |
+ if (priority == null) { |
+ priority = ''; |
+ } |
+ _setProperty(propertyName, value, priority); |
} |
- void setProperty(String propertyName, String value, [String priority = '']) { |
- _ptr.setProperty(propertyName, value, priority); |
+ /** |
+ * Checks to see if CSS Transitions are supported. |
+ */ |
+ static bool get supportsTransitions => true; |
+$endif |
+$!MEMBERS |
+} |
+ |
+class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase { |
+ final Iterable<Element> _elementIterable; |
+ Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable; |
+ |
+ _CssStyleDeclarationSet(this._elementIterable) { |
+ _elementCssStyleDeclarationSetIterable = new List.from( |
+ _elementIterable).map((e) => e.style); |
} |
- String get typeName { return "CSSStyleDeclaration"; } |
+ String getPropertyValue(String propertyName) => |
+ _elementCssStyleDeclarationSetIterable.first.getPropertyValue( |
+ propertyName); |
-""".lstrip() % SOURCE_PATH) |
+ void setProperty(String propertyName, String value, [String priority]) { |
+ _elementCssStyleDeclarationSetIterable.forEach((e) => |
+ e.setProperty(propertyName, value, priority)); |
+ } |
+ // Important note: CssStyleDeclarationSet does NOT implement every method |
+ // available in CssStyleDeclaration. Some of the methods don't make so much |
+ // sense in terms of having a resonable value to return when you're |
+ // considering a list of Elements. You will need to manually add any of the |
+ // items in the MEMBERS set if you want that functionality. |
+} |
+ |
+abstract class CssStyleDeclarationBase { |
+ String getPropertyValue(String propertyName); |
+ void setProperty(String propertyName, String value, [String priority]); |
+""" % SOURCE_PATH) |
- interface_lines = []; |
class_lines = []; |
seen = set() |
for prop in sorted(data, key=lambda p: camelCaseName(p)): |
camel_case_name = camelCaseName(prop) |
upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]; |
- css_name = prop.replace('-webkit-', '${_browserPrefix}') |
+ css_name = prop.replace('-webkit-', '') |
base_css_name = prop.replace('-webkit-', '') |
- if base_css_name in seen: |
+ if base_css_name in seen or base_css_name.startswith('-internal'): |
continue |
seen.add(base_css_name) |
comment = ' /** %s the value of "' + base_css_name + '" */' |
- |
- interface_lines.append(comment % 'Gets') |
- interface_lines.append(""" |
- String get %s; |
- |
-""" % camel_case_name) |
- |
- interface_lines.append(comment % 'Sets') |
- interface_lines.append(""" |
- void set %s(String value); |
- |
-""" % camel_case_name) |
- |
class_lines.append('\n'); |
class_lines.append(comment % 'Gets') |
+ if base_css_name in annotated: |
+ class_lines.append(annotated[base_css_name]) |
class_lines.append(""" |
String get %s => |
getPropertyValue('%s'); |
@@ -201,19 +232,14 @@ class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implement |
""" % (camel_case_name, css_name)) |
class_lines.append(comment % 'Sets') |
+ if base_css_name in annotated: |
+ class_lines.append(annotated[base_css_name]) |
class_lines.append(""" |
void set %s(String value) { |
setProperty('%s', value, ''); |
} |
""" % (camel_case_name, css_name)) |
- interface_file.write(''.join(interface_lines)); |
- interface_file.write('}\n') |
- interface_file.close() |
- |
class_file.write(''.join(class_lines)); |
class_file.write('}\n') |
class_file.close() |
- |
-if __name__ == '__main__': |
- main() |