html_to_wrapper.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # Copyright 2022 The Chromium Authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. # Genaretes a wrapper TS file around a source HTML file holding either
  5. # 1) a Polymer element template or
  6. # 2) an <iron-iconset-svg> definitions
  7. #
  8. # Note: The HTML file must be named either 'icons.html' or be suffixed with
  9. # '_icons.html' for this tool to treat them as #2. Consequently, files holding
  10. # Polymer element templates should not use such naming to be treated as #1.
  11. #
  12. # In case #1 the wrapper exports a getTemplate() function that can be used at
  13. # runtime to import the template. This is useful for implementing Web Components
  14. # using JS modules, where all the HTML needs to reside in a JS file (no more
  15. # HTML imports).
  16. #
  17. # In case #2 the wrapper adds the <iron-iconset-svg> element to <head>, so that
  18. # it can be used by <iron-icon> instances.
  19. import argparse
  20. import io
  21. import shutil
  22. import sys
  23. import tempfile
  24. from os import path, getcwd, makedirs
  25. _HERE_PATH = path.dirname(__file__)
  26. _SRC_PATH = path.normpath(path.join(_HERE_PATH, '..', '..'))
  27. _CWD = getcwd()
  28. sys.path.append(path.join(_SRC_PATH, 'third_party', 'node'))
  29. import node
  30. # Template for non-Polymer elements.
  31. _NON_POLYMER_ELEMENT_TEMPLATE = """import {getTrustedHTML} from \'chrome://resources/js/static_types.js\';
  32. export function getTemplate() {
  33. return getTrustedHTML`<!--_html_template_start_-->%s<!--_html_template_end_-->`;
  34. }"""
  35. # Template for Polymer elements.
  36. _ELEMENT_TEMPLATE = """import {html} from \'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js\';
  37. export function getTemplate() {
  38. return html`<!--_html_template_start_-->%s<!--_html_template_end_-->`;
  39. }"""
  40. _ICONS_TEMPLATE = """import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
  41. import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
  42. const template = html`%s`;
  43. document.head.appendChild(template.content);
  44. """
  45. def main(argv):
  46. parser = argparse.ArgumentParser()
  47. parser.add_argument('--in_folder', required=True)
  48. parser.add_argument('--out_folder', required=True)
  49. parser.add_argument('--in_files', required=True, nargs="*")
  50. parser.add_argument('--minify', action='store_true')
  51. parser.add_argument('--use_js', action='store_true')
  52. parser.add_argument('--template',
  53. choices=['polymer', 'native'],
  54. default='polymer')
  55. args = parser.parse_args(argv)
  56. in_folder = path.normpath(path.join(_CWD, args.in_folder))
  57. out_folder = path.normpath(path.join(_CWD, args.out_folder))
  58. extension = '.js' if args.use_js else '.ts'
  59. results = []
  60. # The folder to be used to read the HTML files to be wrapped.
  61. wrapper_in_folder = in_folder
  62. if args.minify:
  63. # Minify the HTML files with html-minifier before generating the wrapper
  64. # .ts files.
  65. # Note: Passing all HTML files to html-minifier all at once because
  66. # passing them individually takes a lot longer.
  67. # Storing the output in a temporary folder, which is used further below when
  68. # creating the final wrapper files.
  69. tmp_out_dir = tempfile.mkdtemp(dir=out_folder)
  70. try:
  71. wrapper_in_folder = tmp_out_dir
  72. # Using the programmatic Node API to invoke html-minifier, because the
  73. # built-in command line API does not support explicitly specifying
  74. # multiple files to be processed, and only supports specifying an input
  75. # folder, which would lead to potentially processing unnecessary HTML
  76. # files that are not part of the build (stale), or handled by other
  77. # html_to_wrapper targets.
  78. node.RunNode(
  79. [path.join(_HERE_PATH, 'html_minifier.js'), in_folder, tmp_out_dir] +
  80. args.in_files)
  81. except RuntimeError as err:
  82. shutil.rmtree(tmp_out_dir)
  83. raise err
  84. # Wrap the input files (minified or not) with an enclosing .ts file.
  85. for in_file in args.in_files:
  86. wrapper_in_file = path.join(wrapper_in_folder, in_file)
  87. with io.open(wrapper_in_file, encoding='utf-8', mode='r') as f:
  88. html_content = f.read()
  89. wrapper = None
  90. template = _ELEMENT_TEMPLATE \
  91. if args.template == 'polymer' else _NON_POLYMER_ELEMENT_TEMPLATE
  92. filename = path.basename(in_file)
  93. if filename == 'icons.html' or filename.endswith('_icons.html'):
  94. template = _ICONS_TEMPLATE
  95. wrapper = template % html_content
  96. out_folder_for_file = path.join(out_folder, path.dirname(in_file))
  97. makedirs(out_folder_for_file, exist_ok=True)
  98. with io.open(path.join(out_folder, in_file) + extension, mode='wb') as f:
  99. f.write(wrapper.encode('utf-8'))
  100. if args.minify:
  101. # Delete the temporary folder that was holding minified HTML files, no
  102. # longer needed.
  103. shutil.rmtree(tmp_out_dir)
  104. return
  105. if __name__ == '__main__':
  106. main(sys.argv[1:])