Refactor duplicate code for calling into media controls
[WebKit-https.git] / Websites / perf.webkit.org / tools / bundle-v3-scripts.py
1 #!/usr/bin/python
2 # Copyright (C) 2013, 2015, 2016 Apple Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 # 1. Redistributions of source code must retain the above copyright
8 #    notice, this list of conditions and the following disclaimer.
9 # 2. Redistributions in binary form must reproduce the above copyright
10 #    notice, this list of conditions and the following disclaimer in the
11 #    documentation and/or other materials provided with the distribution.
12 #
13 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 # THE POSSIBILITY OF SUCH DAMAGE.
24
25 import os
26 import re
27 import subprocess
28 import sys
29 import xml.dom.minidom
30
31
32 def main(argv):
33     tools_dir = os.path.dirname(__file__)
34     public_v3_dir = os.path.abspath(os.path.join(tools_dir, '..', 'public', 'v3'))
35
36     bundled_script = ''
37
38     index_html = xml.dom.minidom.parse(os.path.join(public_v3_dir, 'index.html'))
39     for template in index_html.getElementsByTagName('template'):
40         if template.getAttribute('id') != 'unbundled-scripts':
41             continue
42         unbundled_scripts = template.getElementsByTagName('script')
43         for script in unbundled_scripts:
44             src = script.getAttribute('src')
45
46             with open(os.path.join(public_v3_dir, src)) as script_file:
47                 script_content = script_file.read()
48                 script_content = re.sub(r'([\"\'])use strict\1;', '', script_content)
49                 script_content = re.sub(r'(?P<prefix>\n\s*static\s+(?P<type>\w+)Template\(\)\s*{[^`]*`)(?P<content>[^`]*)(?P<suffix>`;?\s*})',
50                     compress_template, script_content, re.MULTILINE)
51
52                 bundled_script += script_content
53
54     jsmin = subprocess.Popen(['python', os.path.join(tools_dir, 'jsmin.py')], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
55     minified_script = jsmin.communicate(input=bundled_script)[0]
56
57     new_size = float(len(minified_script))
58     old_size = float(len(bundled_script))
59     print '%d -> %d (%.1f%%)' % (old_size, new_size, new_size / old_size * 100)
60
61     with open(os.path.join(public_v3_dir, 'bundled-scripts.js'), 'w') as bundled_file:
62         bundled_file.write(minified_script)
63
64
65 def compress_template(match):
66     prefix = match.group('prefix')
67     content = match.group('content')
68     suffix = match.group('suffix')
69
70     if match.group('type') == 'css':
71         content = cssminify(content)
72     else:
73         content = re.sub(r'\s+', ' ', content)
74
75     return prefix + content + suffix
76
77
78 def cssminify(css):
79     rules = (
80         (r"\/\*.*?\*\/", ""),          # delete comments
81         (r"\n", ""),                   # delete new lines
82         (r"\s+", " "),                 # change multiple spaces to one space
83         (r"\s?([;{},~>!])\s?", r"\1"), # delete space where it is not needed
84         (r":\s", ":"),                 # delete spaces after colons, but not before. E.g. do not break selectors "a :focus", "b :matches(...)", "c :not(...)" where the leading space is significant
85         (r"\s?([-+])(?:\s(?![0-9(])(?!var))", r"\1"), # delete whitespace around + and - when not followed by a number, paren, or var(). E.g. strip for selector "a + b" but not "calc(a + b)" which requires spaces.
86         (r";}", "}")                   # change ';}' to '}' because the semicolon is not needed
87     )
88
89     css = css.replace("\r\n", "\n")
90     for rule in rules:
91         css = re.compile(rule[0], re.MULTILINE | re.UNICODE | re.DOTALL).sub(rule[1], css)
92     return css
93
94
95 if __name__ == "__main__":
96     main(sys.argv)