OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python2.6 |
2 # | 2 # |
3 # Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 3 # Copyright (c) 2011, 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 template file from css property definitions | 7 """Generates CSSStyleDeclaration from css property definitions defined in WebKit
.""" |
8 defined in WebKit.""" | |
9 | 8 |
10 import tempfile, os | 9 import tempfile, os |
11 | 10 |
12 COMMENT_LINE_PREFIX = ' * ' | 11 COMMENT_LINE_PREFIX = ' * ' |
13 # TODO(efortuna): Pull from DEPS so that we have latest css *in sync* with our | 12 SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' |
14 # Dartium. Then remove the checked in CSSPropertyNames.in. | 13 INPUT_URL = 'http://trac.webkit.org/export/latest/trunk/%s' % SOURCE_PATH |
15 SOURCE_PATH = 'CSSPropertyNames.in' | 14 INTERFACE_FILE = '../../html/src/CSSStyleDeclaration.dart' |
16 #SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in' | 15 CLASS_FILE = '../../html/src/CSSStyleDeclarationWrappingImplementation.dart' |
17 TEMPLATE_FILE = '../templates/html/impl/impl_CSSStyleDeclaration.darttemplate' | |
18 | 16 |
19 # Supported annotations for any specific CSS properties. | 17 def main(): |
20 annotated = { | 18 _, css_names_file = tempfile.mkstemp('.CSSPropertyNames.in') |
21 'transition': '''@SupportedBrowser(SupportedBrowser.CHROME) | 19 try: |
22 @SupportedBrowser(SupportedBrowser.FIREFOX) | 20 if os.system('wget %s -O %s' % (INPUT_URL, css_names_file)): |
23 @SupportedBrowser(SupportedBrowser.IE, '10') | 21 return 1 |
24 @SupportedBrowser(SupportedBrowser.SAFARI)''' | 22 generate_code(css_names_file) |
25 } | 23 print 'Successfully generated %s and %s' % (INTERFACE_FILE, CLASS_FILE) |
| 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 GenerateCssTemplateFile(): | 38 def generate_code(input_path): |
39 data = open(SOURCE_PATH).readlines() | 39 data = open(input_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? | |
43 data = [d[:-1] for d in data | 42 data = [d[:-1] for d in data |
44 if len(d) > 1 | 43 if len(d) > 1 |
45 and not d.startswith('#') | 44 and not d.startswith('#') |
46 and not d.startswith('//') | 45 and not d.startswith('//') |
47 and not '=' in d] | 46 and not '=' in d] |
48 | 47 |
49 class_file = open(TEMPLATE_FILE, 'w') | 48 interface_file = open(INTERFACE_FILE, 'w') |
| 49 class_file = open(CLASS_FILE, 'w') |
50 | 50 |
51 class_file.write(""" | 51 interface_file.write(""" |
52 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 52 // Copyright (c) 2011, 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 THIS TEMPLATE FILE. | 56 // WARNING: Do not edit. |
57 // The template file was generated by scripts/css_code_generator.py | 57 // This file was generated by html/scripts/css_code_generator.py |
58 | 58 |
59 // Source of CSS properties: | 59 // Source of CSS properties: |
60 // %s | 60 // %s |
61 | 61 |
62 part of $LIBRARYNAME; | 62 // TODO(jacobr): add versions that take numeric values in px, miliseconds, etc. |
63 | 63 |
64 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with | 64 interface CSSStyleDeclaration { |
65 $(CLASSNAME)Base $IMPLEMENTS { | |
66 factory $CLASSNAME() => new CssStyleDeclaration.css(''); | |
67 | 65 |
68 factory $CLASSNAME.css(String css) { | 66 String get cssText; |
69 final style = new Element.tag('div').style; | 67 |
70 style.cssText = css; | 68 void set cssText(String value); |
71 return style; | 69 |
| 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); |
72 } | 141 } |
73 | 142 |
74 String getPropertyValue(String propertyName) { | 143 String getPropertyValue(String propertyName) { |
75 var propValue = _getPropertyValueHelper(propertyName); | 144 return _ptr.getPropertyValue(propertyName); |
76 return propValue != null ? propValue : ''; | |
77 } | 145 } |
78 | 146 |
79 String _getPropertyValueHelper(String propertyName) { | 147 bool isPropertyImplicit(String propertyName) { |
80 if (_supportsProperty(_camelCase(propertyName))) { | 148 return _ptr.isPropertyImplicit(propertyName); |
81 return _getPropertyValue(propertyName); | |
82 } else { | |
83 return _getPropertyValue(Device.cssPrefix + propertyName); | |
84 } | |
85 } | 149 } |
86 | 150 |
87 /** | 151 String item(int index) { |
88 * Returns true if the provided *CSS* property name is supported on this | 152 return _ptr.item(index); |
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)); | |
98 } | 153 } |
99 | 154 |
100 bool _supportsProperty(String propertyName) { | 155 String removeProperty(String propertyName) { |
101 $if DART2JS | 156 return _ptr.removeProperty(propertyName); |
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 } | |
126 } | 157 } |
127 | 158 |
128 String _camelCase(String hyphenated) { | 159 void setProperty(String propertyName, String value, [String priority = '']) { |
129 bool firstWord = true; | 160 _ptr.setProperty(propertyName, value, priority); |
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 }); | |
141 } | 161 } |
142 | 162 |
143 $if DART2JS | 163 String get typeName { return "CSSStyleDeclaration"; } |
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 } | |
158 | 164 |
159 /** | 165 """.lstrip() % SOURCE_PATH) |
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 } | |
172 | 166 |
173 /** | 167 interface_lines = []; |
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 | |
210 class_lines = []; | 168 class_lines = []; |
211 | 169 |
212 seen = set() | 170 seen = set() |
213 for prop in sorted(data, key=lambda p: camelCaseName(p)): | 171 for prop in sorted(data, key=lambda p: camelCaseName(p)): |
214 camel_case_name = camelCaseName(prop) | 172 camel_case_name = camelCaseName(prop) |
215 upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]; | 173 upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]; |
216 css_name = prop.replace('-webkit-', '') | 174 css_name = prop.replace('-webkit-', '${_browserPrefix}') |
217 base_css_name = prop.replace('-webkit-', '') | 175 base_css_name = prop.replace('-webkit-', '') |
218 | 176 |
219 if base_css_name in seen or base_css_name.startswith('-internal'): | 177 if base_css_name in seen: |
220 continue | 178 continue |
221 seen.add(base_css_name) | 179 seen.add(base_css_name) |
222 | 180 |
223 comment = ' /** %s the value of "' + base_css_name + '" */' | 181 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 |
224 class_lines.append('\n'); | 195 class_lines.append('\n'); |
225 class_lines.append(comment % 'Gets') | 196 class_lines.append(comment % 'Gets') |
226 if base_css_name in annotated: | |
227 class_lines.append(annotated[base_css_name]) | |
228 class_lines.append(""" | 197 class_lines.append(""" |
229 String get %s => | 198 String get %s => |
230 getPropertyValue('%s'); | 199 getPropertyValue('%s'); |
231 | 200 |
232 """ % (camel_case_name, css_name)) | 201 """ % (camel_case_name, css_name)) |
233 | 202 |
234 class_lines.append(comment % 'Sets') | 203 class_lines.append(comment % 'Sets') |
235 if base_css_name in annotated: | |
236 class_lines.append(annotated[base_css_name]) | |
237 class_lines.append(""" | 204 class_lines.append(""" |
238 void set %s(String value) { | 205 void set %s(String value) { |
239 setProperty('%s', value, ''); | 206 setProperty('%s', value, ''); |
240 } | 207 } |
241 """ % (camel_case_name, css_name)) | 208 """ % (camel_case_name, css_name)) |
242 | 209 |
| 210 interface_file.write(''.join(interface_lines)); |
| 211 interface_file.write('}\n') |
| 212 interface_file.close() |
| 213 |
243 class_file.write(''.join(class_lines)); | 214 class_file.write(''.join(class_lines)); |
244 class_file.write('}\n') | 215 class_file.write('}\n') |
245 class_file.close() | 216 class_file.close() |
| 217 |
| 218 if __name__ == '__main__': |
| 219 main() |
OLD | NEW |