| # Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights |
| # reserved. Use of this source code is governed by a BSD-style license that |
| # can be found in the LICENSE file. |
| |
| from __future__ import absolute_import |
| from __future__ import print_function |
| from cef_json_builder import cef_json_builder |
| import datetime |
| import math |
| import os |
| import sys |
| |
| # Class used to build the cefbuilds HTML file. Generate an index.json file using |
| # the cef_json_builder_example.py tool (or some other means) and then run: |
| # > python cef_html_builder.py index.json index.html.in index.html |
| # |
| # Expected HTML template format is: |
| # |
| # Header |
| # <section:platform_link> |
| # $platform_name$ |
| # </section:platform_link> |
| # <section:platform> |
| # $platform_name$ Builds: |
| # <section:version> |
| # CEF version $cef_version$ Files: |
| # <section:file> |
| # File $file$ size $size$ sha1 $sha1$ |
| # </section:file> |
| # </section:version> |
| # </section:platform> |
| # Footer |
| # |
| # Notes: |
| # - The variables ("$key$") available in each section generally match the key |
| # names that exist in the JSON file for that section. Additional variables are |
| # exposed where needed. |
| # - Some global variables like "$year$" will be replaced in the whole template |
| # before further parsing occurs. |
| |
| |
| class cef_html_builder: |
| """ Class used to build the cefbuilds HTML file. """ |
| |
| def __init__(self, branding=''): |
| """ Create a new cef_html_builder object. """ |
| self.clear() |
| self._branding = branding |
| |
| def clear(self): |
| """ Clear the contents of this object. """ |
| self._parts = {} |
| return |
| |
| @staticmethod |
| def _token(key): |
| # Returns the token representation of |key| |
| return '$' + key + '$' |
| |
| @staticmethod |
| def _section_tags(section): |
| # Returns the start and end tags for |section| |
| return ('<section:' + section + '>', '</section:' + section + '>') |
| |
| @staticmethod |
| def _section_key(section): |
| # Returns the replacement key for |section| |
| return section + '_section' |
| |
| @staticmethod |
| def _replace(str, key, value): |
| # Replaces all instances of |key| with |value| in |str|. |
| return str.replace(cef_html_builder._token(key), value) |
| |
| @staticmethod |
| def _replace_all(str, dict): |
| for (key, value) in dict.items(): |
| str = cef_html_builder._replace(str, key, value) |
| return str |
| |
| @staticmethod |
| def _extract(str, section): |
| # Extracts the |section| region and replaces it with a token named |
| # "<section>_section". |
| (start_tag, end_tag) = cef_html_builder._section_tags(section) |
| start_pos = str.find(start_tag) |
| end_pos = str.rfind(end_tag) |
| if start_pos < 0 or end_pos < 0: |
| raise Exception('Failed to find section %s' % section) |
| top = str[:start_pos] |
| middle = str[start_pos + len(start_tag):end_pos] |
| bottom = str[end_pos + len(end_tag):] |
| return ( |
| top + cef_html_builder._token(cef_html_builder._section_key(section)) + |
| bottom, middle) |
| |
| def load(self, html_template): |
| """ Load the specified |html_template| string. """ |
| self.clear() |
| root = html_template |
| |
| # Extract the platform link section from root. |
| (root, platform_link) = self._extract(root, 'platform_link') |
| |
| # Extract platform section from root. |
| (root, platform) = self._extract(root, 'platform') |
| |
| # Extract version section from platform. |
| (platform, version) = self._extract(platform, 'version') |
| |
| # Extract file section from version. |
| (version, file) = self._extract(version, 'file') |
| |
| self._parts = { |
| 'root': root, |
| 'platform_link': platform_link, |
| 'platform': platform, |
| 'version': version, |
| 'file': file |
| } |
| |
| @staticmethod |
| def _get_platform_name(platform): |
| return { |
| 'linux32': 'Linux 32-bit', |
| 'linux64': 'Linux 64-bit', |
| 'linuxarm': 'Linux ARM', |
| 'linuxarm64': 'Linux ARM64', |
| 'macosx64': 'Mac OS X 64-bit', |
| 'windows32': 'Windows 32-bit', |
| 'windows64': 'Windows 64-bit' |
| }[platform] |
| |
| @staticmethod |
| def _get_type_name(type): |
| return { |
| 'standard': 'Standard Distribution', |
| 'minimal': 'Minimal Distribution', |
| 'client': 'Sample Application', |
| 'debug_symbols': 'Debug Symbols', |
| 'release_symbols': 'Release Symbols' |
| }[type] |
| |
| @staticmethod |
| def _get_date(date): |
| return date.strftime('%m/%d/%Y') |
| |
| @staticmethod |
| def _get_file_size(size): |
| if (size == 0): |
| return '0B' |
| size_name = ('B', 'KB', 'MB', 'GB') |
| i = int(math.floor(math.log(size, 1024))) |
| p = math.pow(1024, i) |
| s = round(size / p, 2) |
| return '%.2f %s' % (s, size_name[i]) |
| |
| @staticmethod |
| def _get_cef_source_url(cef_version): |
| if cef_version.find('+chromium') > 0: |
| # New-style CEF version numbers include the Chromium version number. |
| # Example: 74.0.1+g62d140e+chromium-74.0.3729.6 |
| chromium_version = cef_version[cef_version.rfind('-') + 1:] |
| branch = chromium_version.split('.')[2] |
| else: |
| branch = cef_version.split('.')[1] |
| return 'https://bitbucket.org/chromiumembedded/cef/get/%s.tar.bz2' % branch |
| |
| @staticmethod |
| def _get_chromium_source_url(chromium_version): |
| if chromium_version == 'master': |
| return 'https://chromium.googlesource.com/chromium/src.git' |
| return 'https://gsdview.appspot.com/chromium-browser-official/chromium-%s.tar.xz' % chromium_version |
| |
| @staticmethod |
| def _get_file_url(platform, cef_version, file): |
| return file['name'].replace('+', '%2B') |
| |
| @staticmethod |
| def _get_sha1_url(platform, cef_version, file): |
| return cef_html_builder._get_file_url(platform, cef_version, file) + '.sha1' |
| |
| @staticmethod |
| def _get_tooltip_text(platform, cef_version, file): |
| if platform.startswith('linux'): |
| sample_app = 'cefsimple' |
| else: |
| sample_app = 'cefclient' |
| return { |
| 'standard': |
| 'Standard binary distribution. Includes header files, libcef_dll_wrapper source code, binary files, CMake configuration files and source code for the cefclient and cefsimple sample applications. See the included README.txt file for usage and build requirements.', |
| 'minimal': |
| 'Minimal binary distribution. Includes header files, libcef_dll_wrapper source code, Release build binary files and CMake configuration files. Does not include Debug build binary files or sample application source code. See the included README.txt file for usage and build requirements.', |
| 'client': |
| 'Release build of the ' + sample_app + |
| ' sample application. See the included README.txt file for usage requirements.', |
| 'debug_symbols': |
| 'Debug build symbols. Must be extracted and placed next to the CEF Debug binary file with the same name and version.', |
| 'release_symbols': |
| 'Release build symbols. Must be extracted and placed next to the CEF Release binary file with the same name and version.' |
| }[file['type']] |
| |
| def generate(self, json_builder): |
| """ Generate HTML output based on the contents of |json_builder|. """ |
| if not isinstance(json_builder, cef_json_builder): |
| raise Exception('Invalid argument') |
| |
| # Substitution values are augmented at each nesting level. |
| subs = { |
| 'year': '2016', |
| 'branding': self._branding, |
| } |
| |
| # Substitute variables. |
| root_str = self._replace_all(self._parts['root'], subs) |
| |
| platform_link_strs = [] |
| platform_strs = [] |
| for platform in json_builder.get_platforms(): |
| subs['platform'] = platform |
| subs['platform_name'] = self._get_platform_name(platform) |
| |
| # Substitute variables. |
| platform_link_str = self._replace_all(self._parts['platform_link'], subs) |
| platform_str = self._replace_all(self._parts['platform'], subs) |
| |
| version_strs = [] |
| for version in json_builder.get_versions(platform): |
| subs['cef_version'] = version['cef_version'] |
| subs['chromium_version'] = version['chromium_version'] |
| subs['last_modified'] = self._get_date( |
| version['files'][0]['last_modified']) |
| subs['cef_source_url'] = self._get_cef_source_url( |
| version['cef_version']) |
| subs['chromium_source_url'] = self._get_chromium_source_url( |
| version['chromium_version']) |
| |
| # Substitute variables. |
| version_str = self._replace_all(self._parts['version'], subs) |
| |
| file_strs = {} |
| for file in version['files']: |
| subs['last_modified'] = self._get_date(file['last_modified']) |
| subs['name'] = file['name'] |
| subs['sha1'] = file['sha1'] |
| subs['size'] = self._get_file_size(file['size']) |
| subs['type'] = file['type'] |
| subs['type_name'] = self._get_type_name(file['type']) |
| subs['file_url'] = self._get_file_url(platform, |
| version['cef_version'], file) |
| subs['sha1_url'] = self._get_sha1_url(platform, |
| version['cef_version'], file) |
| subs['tooltip_text'] = self._get_tooltip_text( |
| platform, version['cef_version'], file) |
| |
| # Substitute variables. |
| file_str = self._replace_all(self._parts['file'], subs) |
| file_strs[file['type']] = file_str |
| |
| if len(file_strs) > 0: |
| # Always output file types in the same order. |
| file_out = '' |
| type_order = [ |
| 'standard', 'minimal', 'client', 'debug_symbols', |
| 'release_symbols' |
| ] |
| for type in type_order: |
| if type in file_strs: |
| file_out = file_out + file_strs[type] |
| |
| # Insert files. |
| version_str = self._replace(version_str, |
| self._section_key('file'), file_out) |
| version_strs.append(version_str) |
| |
| if len(version_strs) > 0: |
| # Insert versions. |
| platform_str = self._replace(platform_str, |
| self._section_key('version'), |
| "".join(version_strs)) |
| platform_strs.append(platform_str) |
| platform_link_strs.append(platform_link_str) |
| |
| if len(platform_strs) > 0: |
| # Insert platforms. |
| root_str = self._replace(root_str, |
| self._section_key('platform_link'), |
| "".join(platform_link_strs)) |
| root_str = self._replace(root_str, |
| self._section_key('platform'), |
| "".join(platform_strs)) |
| |
| return root_str |
| |
| |
| # Program entry point. |
| if __name__ == '__main__': |
| # Verify command-line arguments. |
| if len(sys.argv) < 4: |
| sys.stderr.write('Usage: %s <json_file_in> <html_file_in> <html_file_out>\n' |
| % sys.argv[0]) |
| sys.exit() |
| |
| json_file_in = sys.argv[1] |
| html_file_in = sys.argv[2] |
| html_file_out = sys.argv[3] |
| |
| # Create the HTML builder and load the HTML template. |
| print('--> Reading %s' % html_file_in) |
| html_builder = cef_html_builder() |
| with open(html_file_in, 'r') as f: |
| html_builder.load(f.read()) |
| |
| # Create the JSON builder and load the JSON file. |
| print('--> Reading %s' % json_file_in) |
| json_builder = cef_json_builder(silent=False) |
| with open(json_file_in, 'r') as f: |
| json_builder.load(f.read()) |
| |
| # Write the HTML output file. |
| print('--> Writing %s' % html_file_out) |
| with open(html_file_out, 'w') as f: |
| f.write(html_builder.generate(json_builder)) |