| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 | |
| 3 # Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. | |
| 4 # | |
| 5 # Redistribution and use in source and binary forms, with or without | |
| 6 # modification, are permitted provided that the following conditions | |
| 7 # are met: | |
| 8 # | |
| 9 # 1. Redistributions of source code must retain the above | |
| 10 # copyright notice, this list of conditions and the following | |
| 11 # disclaimer. | |
| 12 # 2. Redistributions in binary form must reproduce the above | |
| 13 # copyright notice, this list of conditions and the following | |
| 14 # disclaimer in the documentation and/or other materials | |
| 15 # provided with the distribution. | |
| 16 # | |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY | |
| 18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 20 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE | |
| 21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |
| 22 # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 23 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 24 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
| 26 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | |
| 27 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 28 # SUCH DAMAGE. | |
| 29 | |
| 30 import logging | |
| 31 import re | |
| 32 | |
| 33 from webkitpy.common.host import Host | |
| 34 from webkitpy.common.webkit_finder import WebKitFinder | |
| 35 from HTMLParser import HTMLParser | |
| 36 | |
| 37 | |
| 38 _log = logging.getLogger(__name__) | |
| 39 | |
| 40 | |
| 41 def convert_for_webkit(new_path, filename, host=Host()): | |
| 42 """ Converts a file's |contents| so it will function correctly in its |new_p
ath| in Webkit. | |
| 43 | |
| 44 Returns the list of modified properties and the modified text if the file wa
s modifed, None otherwise.""" | |
| 45 contents = host.filesystem.read_binary_file(filename) | |
| 46 converter = _W3CTestConverter(new_path, filename, host) | |
| 47 if filename.endswith('.css'): | |
| 48 return converter.add_webkit_prefix_to_unprefixed_properties(contents) | |
| 49 else: | |
| 50 converter.feed(contents) | |
| 51 converter.close() | |
| 52 return converter.output() | |
| 53 | |
| 54 | |
| 55 class _W3CTestConverter(HTMLParser): | |
| 56 def __init__(self, new_path, filename, host=Host()): | |
| 57 HTMLParser.__init__(self) | |
| 58 | |
| 59 self._host = host | |
| 60 self._filesystem = self._host.filesystem | |
| 61 self._webkit_root = WebKitFinder(self._filesystem).webkit_base() | |
| 62 | |
| 63 self.converted_data = [] | |
| 64 self.converted_properties = [] | |
| 65 self.in_style_tag = False | |
| 66 self.style_data = [] | |
| 67 self.filename = filename | |
| 68 | |
| 69 resources_path = self.path_from_webkit_root('tests', 'resources') | |
| 70 resources_relpath = self._filesystem.relpath(resources_path, new_path) | |
| 71 self.resources_relpath = resources_relpath | |
| 72 | |
| 73 # These settings might vary between WebKit and Blink | |
| 74 self._css_property_file = self.path_from_webkit_root('Source', 'core', '
css', 'CSSProperties.in') | |
| 75 | |
| 76 self.prefixed_properties = self.read_webkit_prefixed_css_property_list() | |
| 77 | |
| 78 self.prefixed_properties = self.read_webkit_prefixed_css_property_list() | |
| 79 prop_regex = '([\s{]|^)(' + "|".join(prop.replace('-webkit-', '') for pr
op in self.prefixed_properties) + ')(\s+:|:)' | |
| 80 self.prop_re = re.compile(prop_regex) | |
| 81 | |
| 82 def output(self): | |
| 83 return (self.converted_properties, ''.join(self.converted_data)) | |
| 84 | |
| 85 def path_from_webkit_root(self, *comps): | |
| 86 return self._filesystem.abspath(self._filesystem.join(self._webkit_root,
*comps)) | |
| 87 | |
| 88 def read_webkit_prefixed_css_property_list(self): | |
| 89 prefixed_properties = [] | |
| 90 unprefixed_properties = set() | |
| 91 | |
| 92 contents = self._filesystem.read_text_file(self._css_property_file) | |
| 93 for line in contents.splitlines(): | |
| 94 if re.match('^(#|//|$)', line): | |
| 95 # skip comments and preprocessor directives | |
| 96 continue | |
| 97 prop = line.split()[0] | |
| 98 # Find properties starting with the -webkit- prefix. | |
| 99 match = re.match('-webkit-([\w|-]*)', prop) | |
| 100 if match: | |
| 101 prefixed_properties.append(match.group(1)) | |
| 102 else: | |
| 103 unprefixed_properties.add(prop.strip()) | |
| 104 | |
| 105 # Ignore any prefixed properties for which an unprefixed version is supp
orted | |
| 106 return [prop for prop in prefixed_properties if prop not in unprefixed_p
roperties] | |
| 107 | |
| 108 def add_webkit_prefix_to_unprefixed_properties(self, text): | |
| 109 """ Searches |text| for instances of properties requiring the -webkit- p
refix and adds the prefix to them. | |
| 110 | |
| 111 Returns the list of converted properties and the modified text.""" | |
| 112 | |
| 113 converted_properties = set() | |
| 114 text_chunks = [] | |
| 115 cur_pos = 0 | |
| 116 for m in self.prop_re.finditer(text): | |
| 117 text_chunks.extend([text[cur_pos:m.start()], m.group(1), '-webkit-',
m.group(2), m.group(3)]) | |
| 118 converted_properties.add(m.group(2)) | |
| 119 cur_pos = m.end() | |
| 120 text_chunks.append(text[cur_pos:]) | |
| 121 | |
| 122 for prop in converted_properties: | |
| 123 _log.info(' converting %s', prop) | |
| 124 | |
| 125 # FIXME: Handle the JS versions of these properties and GetComputedStyle
, too. | |
| 126 return (converted_properties, ''.join(text_chunks)) | |
| 127 | |
| 128 def convert_style_data(self, data): | |
| 129 converted = self.add_webkit_prefix_to_unprefixed_properties(data) | |
| 130 if converted[0]: | |
| 131 self.converted_properties.extend(list(converted[0])) | |
| 132 return converted[1] | |
| 133 | |
| 134 def convert_attributes_if_needed(self, tag, attrs): | |
| 135 converted = self.get_starttag_text() | |
| 136 if tag in ('script', 'link'): | |
| 137 target_attr = 'src' | |
| 138 if tag != 'script': | |
| 139 target_attr = 'href' | |
| 140 for attr_name, attr_value in attrs: | |
| 141 if attr_name == target_attr: | |
| 142 new_path = re.sub('/resources/testharness', | |
| 143 self.resources_relpath + '/testharness', | |
| 144 attr_value) | |
| 145 converted = re.sub(attr_value, new_path, converted) | |
| 146 new_path = re.sub('/common/vendor-prefix', | |
| 147 self.resources_relpath + '/vendor-prefix', | |
| 148 attr_value) | |
| 149 converted = re.sub(attr_value, new_path, converted) | |
| 150 | |
| 151 for attr_name, attr_value in attrs: | |
| 152 if attr_name == 'style': | |
| 153 new_style = self.convert_style_data(attr_value) | |
| 154 converted = re.sub(attr_value, new_style, converted) | |
| 155 if attr_name == 'class' and 'instructions' in attr_value: | |
| 156 # Always hide instructions, they're for manual testers. | |
| 157 converted = re.sub(' style=".*?"', '', converted) | |
| 158 converted = re.sub('\>', ' style="display:none">', converted) | |
| 159 | |
| 160 self.converted_data.append(converted) | |
| 161 | |
| 162 def handle_starttag(self, tag, attrs): | |
| 163 if tag == 'style': | |
| 164 self.in_style_tag = True | |
| 165 self.convert_attributes_if_needed(tag, attrs) | |
| 166 | |
| 167 def handle_endtag(self, tag): | |
| 168 if tag == 'style': | |
| 169 self.converted_data.append(self.convert_style_data(''.join(self.styl
e_data))) | |
| 170 self.in_style_tag = False | |
| 171 self.style_data = [] | |
| 172 self.converted_data.extend(['</', tag, '>']) | |
| 173 | |
| 174 def handle_startendtag(self, tag, attrs): | |
| 175 self.convert_attributes_if_needed(tag, attrs) | |
| 176 | |
| 177 def handle_data(self, data): | |
| 178 if self.in_style_tag: | |
| 179 self.style_data.append(data) | |
| 180 else: | |
| 181 self.converted_data.append(data) | |
| 182 | |
| 183 def handle_entityref(self, name): | |
| 184 self.converted_data.extend(['&', name, ';']) | |
| 185 | |
| 186 def handle_charref(self, name): | |
| 187 self.converted_data.extend(['&#', name, ';']) | |
| 188 | |
| 189 def handle_comment(self, data): | |
| 190 self.converted_data.extend(['<!-- ', data, ' -->']) | |
| 191 | |
| 192 def handle_decl(self, decl): | |
| 193 self.converted_data.extend(['<!', decl, '>']) | |
| 194 | |
| 195 def handle_pi(self, data): | |
| 196 self.converted_data.extend(['<?', data, '>']) | |
| 197 | |
| OLD | NEW |