OLD | NEW |
1 #!/usr/bin/python2.6 | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
4 # for details. All rights reserved. Use of this source code is governed by a | 4 # for details. All rights reserved. Use of this source code is governed by a |
5 # BSD-style license that can be found in the LICENSE file. | 5 # BSD-style license that can be found in the LICENSE file. |
6 | 6 |
7 """Generates CSSStyleDeclaration from css property definitions defined in WebKit
.""" | 7 """Generates CSSStyleDeclaration template file from css property definitions |
| 8 defined in WebKit.""" |
8 | 9 |
9 import tempfile, os | 10 import tempfile, os |
10 | 11 |
11 COMMENT_LINE_PREFIX = ' * ' | 12 COMMENT_LINE_PREFIX = ' * ' |
12 SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' | 13 # TODO(efortuna): Pull from DEPS so that we have latest css *in sync* with our |
13 INPUT_URL = 'http://trac.webkit.org/export/latest/trunk/%s' % SOURCE_PATH | 14 # Dartium. Then remove the checked in CSSPropertyNames.in. |
14 INTERFACE_FILE = '../../html/src/CSSStyleDeclaration.dart' | 15 SOURCE_PATH = 'CSSPropertyNames.in' |
15 CLASS_FILE = '../../html/src/CSSStyleDeclarationWrappingImplementation.dart' | 16 #SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' |
| 17 TEMPLATE_FILE = '../templates/html/impl/impl_CSSStyleDeclaration.darttemplate' |
16 | 18 |
17 def main(): | 19 # Supported annotations for any specific CSS properties. |
18 _, css_names_file = tempfile.mkstemp('.CSSPropertyNames.in') | 20 annotated = { |
19 try: | 21 'transition': '''@SupportedBrowser(SupportedBrowser.CHROME) |
20 if os.system('wget %s -O %s' % (INPUT_URL, css_names_file)): | 22 @SupportedBrowser(SupportedBrowser.FIREFOX) |
21 return 1 | 23 @SupportedBrowser(SupportedBrowser.IE, '10') |
22 generate_code(css_names_file) | 24 @SupportedBrowser(SupportedBrowser.SAFARI)''' |
23 print 'Successfully generated %s and %s' % (INTERFACE_FILE, CLASS_FILE) | 25 } |
24 finally: | |
25 os.remove(css_names_file) | |
26 | 26 |
27 def camelCaseName(name): | 27 def camelCaseName(name): |
28 """Convert a CSS property name to a lowerCamelCase name.""" | 28 """Convert a CSS property name to a lowerCamelCase name.""" |
29 name = name.replace('-webkit-', '') | 29 name = name.replace('-webkit-', '') |
30 words = [] | 30 words = [] |
31 for word in name.split('-'): | 31 for word in name.split('-'): |
32 if words: | 32 if words: |
33 words.append(word.title()) | 33 words.append(word.title()) |
34 else: | 34 else: |
35 words.append(word) | 35 words.append(word) |
36 return ''.join(words) | 36 return ''.join(words) |
37 | 37 |
38 def generate_code(input_path): | 38 def GenerateCssTemplateFile(): |
39 data = open(input_path).readlines() | 39 data = open(SOURCE_PATH).readlines() |
40 | 40 |
41 # filter CSSPropertyNames.in to only the properties | 41 # filter CSSPropertyNames.in to only the properties |
| 42 # TODO(efortuna): do we also want CSSPropertyNames.in? |
42 data = [d[:-1] for d in data | 43 data = [d[:-1] for d in data |
43 if len(d) > 1 | 44 if len(d) > 1 |
44 and not d.startswith('#') | 45 and not d.startswith('#') |
45 and not d.startswith('//') | 46 and not d.startswith('//') |
46 and not '=' in d] | 47 and not '=' in d] |
47 | 48 |
48 interface_file = open(INTERFACE_FILE, 'w') | 49 class_file = open(TEMPLATE_FILE, 'w') |
49 class_file = open(CLASS_FILE, 'w') | |
50 | 50 |
51 interface_file.write(""" | 51 class_file.write(""" |
52 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 52 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
53 // for details. All rights reserved. Use of this source code is governed by a | 53 // for details. All rights reserved. Use of this source code is governed by a |
54 // BSD-style license that can be found in the LICENSE file. | 54 // BSD-style license that can be found in the LICENSE file. |
55 | 55 |
56 // WARNING: Do not edit. | 56 // WARNING: DO NOT EDIT THIS TEMPLATE FILE. |
57 // This file was generated by html/scripts/css_code_generator.py | 57 // The template file was generated by scripts/css_code_generator.py |
58 | 58 |
59 // Source of CSS properties: | 59 // Source of CSS properties: |
60 // %s | 60 // %s |
61 | 61 |
62 // TODO(jacobr): add versions that take numeric values in px, miliseconds, etc. | 62 part of $LIBRARYNAME; |
63 | 63 |
64 interface CSSStyleDeclaration { | 64 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with |
| 65 $(CLASSNAME)Base $IMPLEMENTS { |
| 66 factory $CLASSNAME() => new CssStyleDeclaration.css(''); |
65 | 67 |
66 String get cssText; | 68 factory $CLASSNAME.css(String css) { |
67 | 69 final style = new Element.tag('div').style; |
68 void set cssText(String value); | 70 style.cssText = css; |
69 | 71 return style; |
70 int get length; | |
71 | |
72 CSSRule get parentRule; | |
73 | |
74 CSSValue getPropertyCSSValue(String propertyName); | |
75 | |
76 String getPropertyPriority(String propertyName); | |
77 | |
78 String getPropertyShorthand(String propertyName); | |
79 | |
80 String getPropertyValue(String propertyName); | |
81 | |
82 bool isPropertyImplicit(String propertyName); | |
83 | |
84 String item(int index); | |
85 | |
86 String removeProperty(String propertyName); | |
87 | |
88 void setProperty(String propertyName, String value, [String priority]); | |
89 | |
90 """.lstrip() % SOURCE_PATH) | |
91 | |
92 | |
93 class_file.write(""" | |
94 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
95 // for details. All rights reserved. Use of this source code is governed by a | |
96 // BSD-style license that can be found in the LICENSE file. | |
97 | |
98 // WARNING: Do not edit. | |
99 // This file was generated by html/scripts/css_code_generator.py | |
100 | |
101 // Source of CSS properties: | |
102 // %s | |
103 | |
104 // TODO(jacobr): add versions that take numeric values in px, miliseconds, etc. | |
105 | |
106 class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implement
s CSSStyleDeclaration { | |
107 static String _cachedBrowserPrefix; | |
108 | |
109 CSSStyleDeclarationWrappingImplementation._wrap(ptr) : super._wrap(ptr) {} | |
110 | |
111 static String get _browserPrefix { | |
112 if (_cachedBrowserPrefix == null) { | |
113 if (_Device.isFirefox) { | |
114 _cachedBrowserPrefix = '-moz-'; | |
115 } else { | |
116 _cachedBrowserPrefix = '-webkit-'; | |
117 } | |
118 // TODO(jacobr): support IE 9.0 and Opera as well. | |
119 } | |
120 return _cachedBrowserPrefix; | |
121 } | |
122 | |
123 String get cssText { return _ptr.cssText; } | |
124 | |
125 void set cssText(String value) { _ptr.cssText = value; } | |
126 | |
127 int get length { return _ptr.length; } | |
128 | |
129 CSSRule get parentRule { return LevelDom.wrapCSSRule(_ptr.parentRule); } | |
130 | |
131 CSSValue getPropertyCSSValue(String propertyName) { | |
132 return LevelDom.wrapCSSValue(_ptr.getPropertyCSSValue(propertyName)); | |
133 } | |
134 | |
135 String getPropertyPriority(String propertyName) { | |
136 return _ptr.getPropertyPriority(propertyName); | |
137 } | |
138 | |
139 String getPropertyShorthand(String propertyName) { | |
140 return _ptr.getPropertyShorthand(propertyName); | |
141 } | 72 } |
142 | 73 |
143 String getPropertyValue(String propertyName) { | 74 String getPropertyValue(String propertyName) { |
144 return _ptr.getPropertyValue(propertyName); | 75 var propValue = _getPropertyValueHelper(propertyName); |
| 76 return propValue != null ? propValue : ''; |
145 } | 77 } |
146 | 78 |
147 bool isPropertyImplicit(String propertyName) { | 79 String _getPropertyValueHelper(String propertyName) { |
148 return _ptr.isPropertyImplicit(propertyName); | 80 if (_supportsProperty(_camelCase(propertyName))) { |
| 81 return _getPropertyValue(propertyName); |
| 82 } else { |
| 83 return _getPropertyValue(Device.cssPrefix + propertyName); |
| 84 } |
149 } | 85 } |
150 | 86 |
151 String item(int index) { | 87 /** |
152 return _ptr.item(index); | 88 * Returns true if the provided *CSS* property name is supported on this |
| 89 * element. |
| 90 * |
| 91 * Please note the property name camelCase, not-hyphens. This |
| 92 * method returns true if the property is accessible via an unprefixed _or_ |
| 93 * prefixed property. |
| 94 */ |
| 95 bool supportsProperty(String propertyName) { |
| 96 return _supportsProperty(propertyName) || |
| 97 _supportsProperty(_camelCase(Device.cssPrefix + propertyName)); |
153 } | 98 } |
154 | 99 |
155 String removeProperty(String propertyName) { | 100 bool _supportsProperty(String propertyName) { |
156 return _ptr.removeProperty(propertyName); | 101 $if DART2JS |
| 102 return JS('bool', '# in #', propertyName, this); |
| 103 $else |
| 104 // You can't just check the value of a property, because there is no way |
| 105 // to distinguish between property not being present in the browser and |
| 106 // not having a value at all. (Ultimately we'll want the native method to |
| 107 // return null if the property doesn't exist and empty string if it's |
| 108 // defined but just doesn't have a value. |
| 109 return _hasProperty(propertyName); |
| 110 $endif |
| 111 } |
| 112 $if DARTIUM |
| 113 |
| 114 bool _hasProperty(String propertyName) => |
| 115 _blink.BlinkCSSStyleDeclaration.$__propertyQuery___Callback(this, property
Name); |
| 116 $endif |
| 117 |
| 118 @DomName('CSSStyleDeclaration.setProperty') |
| 119 void setProperty(String propertyName, String value, [String priority]) { |
| 120 if (_supportsProperty(_camelCase(propertyName))) { |
| 121 return _setPropertyHelper(propertyName, value, priority); |
| 122 } else { |
| 123 return _setPropertyHelper(Device.cssPrefix + propertyName, value, |
| 124 priority); |
| 125 } |
157 } | 126 } |
158 | 127 |
159 void setProperty(String propertyName, String value, [String priority = '']) { | 128 String _camelCase(String hyphenated) { |
160 _ptr.setProperty(propertyName, value, priority); | 129 bool firstWord = true; |
| 130 return hyphenated.splitMapJoin('-', onMatch : (_) => '', |
| 131 onNonMatch : (String word) { |
| 132 if (word.length > 0) { |
| 133 if (firstWord) { |
| 134 firstWord = false; |
| 135 return word; |
| 136 } |
| 137 return word[0].toUpperCase() + word.substring(1); |
| 138 } |
| 139 return ''; |
| 140 }); |
161 } | 141 } |
162 | 142 |
163 String get typeName { return "CSSStyleDeclaration"; } | 143 $if DART2JS |
| 144 void _setPropertyHelper(String propertyName, String value, [String priority])
{ |
| 145 // try/catch for IE9 which throws on unsupported values. |
| 146 try { |
| 147 if (value == null) value = ''; |
| 148 if (priority == null) { |
| 149 priority = ''; |
| 150 } |
| 151 JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority); |
| 152 // Bug #2772, IE9 requires a poke to actually apply the value. |
| 153 if (JS('bool', '!!#.setAttribute', this)) { |
| 154 JS('void', '#.setAttribute(#, #)', this, propertyName, value); |
| 155 } |
| 156 } catch (e) {} |
| 157 } |
164 | 158 |
165 """.lstrip() % SOURCE_PATH) | 159 /** |
| 160 * Checks to see if CSS Transitions are supported. |
| 161 */ |
| 162 static bool get supportsTransitions { |
| 163 return supportsProperty('transition'); |
| 164 } |
| 165 $else |
| 166 void _setPropertyHelper(String propertyName, String value, [String priority])
{ |
| 167 if (priority == null) { |
| 168 priority = ''; |
| 169 } |
| 170 _setProperty(propertyName, value, priority); |
| 171 } |
166 | 172 |
167 interface_lines = []; | 173 /** |
| 174 * Checks to see if CSS Transitions are supported. |
| 175 */ |
| 176 static bool get supportsTransitions => true; |
| 177 $endif |
| 178 $!MEMBERS |
| 179 } |
| 180 |
| 181 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase { |
| 182 final Iterable<Element> _elementIterable; |
| 183 Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable; |
| 184 |
| 185 _CssStyleDeclarationSet(this._elementIterable) { |
| 186 _elementCssStyleDeclarationSetIterable = new List.from( |
| 187 _elementIterable).map((e) => e.style); |
| 188 } |
| 189 |
| 190 String getPropertyValue(String propertyName) => |
| 191 _elementCssStyleDeclarationSetIterable.first.getPropertyValue( |
| 192 propertyName); |
| 193 |
| 194 void setProperty(String propertyName, String value, [String priority]) { |
| 195 _elementCssStyleDeclarationSetIterable.forEach((e) => |
| 196 e.setProperty(propertyName, value, priority)); |
| 197 } |
| 198 // Important note: CssStyleDeclarationSet does NOT implement every method |
| 199 // available in CssStyleDeclaration. Some of the methods don't make so much |
| 200 // sense in terms of having a resonable value to return when you're |
| 201 // considering a list of Elements. You will need to manually add any of the |
| 202 // items in the MEMBERS set if you want that functionality. |
| 203 } |
| 204 |
| 205 abstract class CssStyleDeclarationBase { |
| 206 String getPropertyValue(String propertyName); |
| 207 void setProperty(String propertyName, String value, [String priority]); |
| 208 """ % SOURCE_PATH) |
| 209 |
168 class_lines = []; | 210 class_lines = []; |
169 | 211 |
170 seen = set() | 212 seen = set() |
171 for prop in sorted(data, key=lambda p: camelCaseName(p)): | 213 for prop in sorted(data, key=lambda p: camelCaseName(p)): |
172 camel_case_name = camelCaseName(prop) | 214 camel_case_name = camelCaseName(prop) |
173 upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]; | 215 upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]; |
174 css_name = prop.replace('-webkit-', '${_browserPrefix}') | 216 css_name = prop.replace('-webkit-', '') |
175 base_css_name = prop.replace('-webkit-', '') | 217 base_css_name = prop.replace('-webkit-', '') |
176 | 218 |
177 if base_css_name in seen: | 219 if base_css_name in seen or base_css_name.startswith('-internal'): |
178 continue | 220 continue |
179 seen.add(base_css_name) | 221 seen.add(base_css_name) |
180 | 222 |
181 comment = ' /** %s the value of "' + base_css_name + '" */' | 223 comment = ' /** %s the value of "' + base_css_name + '" */' |
182 | |
183 interface_lines.append(comment % 'Gets') | |
184 interface_lines.append(""" | |
185 String get %s; | |
186 | |
187 """ % camel_case_name) | |
188 | |
189 interface_lines.append(comment % 'Sets') | |
190 interface_lines.append(""" | |
191 void set %s(String value); | |
192 | |
193 """ % camel_case_name) | |
194 | |
195 class_lines.append('\n'); | 224 class_lines.append('\n'); |
196 class_lines.append(comment % 'Gets') | 225 class_lines.append(comment % 'Gets') |
| 226 if base_css_name in annotated: |
| 227 class_lines.append(annotated[base_css_name]) |
197 class_lines.append(""" | 228 class_lines.append(""" |
198 String get %s => | 229 String get %s => |
199 getPropertyValue('%s'); | 230 getPropertyValue('%s'); |
200 | 231 |
201 """ % (camel_case_name, css_name)) | 232 """ % (camel_case_name, css_name)) |
202 | 233 |
203 class_lines.append(comment % 'Sets') | 234 class_lines.append(comment % 'Sets') |
| 235 if base_css_name in annotated: |
| 236 class_lines.append(annotated[base_css_name]) |
204 class_lines.append(""" | 237 class_lines.append(""" |
205 void set %s(String value) { | 238 void set %s(String value) { |
206 setProperty('%s', value, ''); | 239 setProperty('%s', value, ''); |
207 } | 240 } |
208 """ % (camel_case_name, css_name)) | 241 """ % (camel_case_name, css_name)) |
209 | 242 |
210 interface_file.write(''.join(interface_lines)); | |
211 interface_file.write('}\n') | |
212 interface_file.close() | |
213 | |
214 class_file.write(''.join(class_lines)); | 243 class_file.write(''.join(class_lines)); |
215 class_file.write('}\n') | 244 class_file.write('}\n') |
216 class_file.close() | 245 class_file.close() |
217 | |
218 if __name__ == '__main__': | |
219 main() | |
OLD | NEW |