[dart:html] Script to generate the prototype JS interop CSS properties
Generates a `tools/dom/scripts/prototype_css_properties.dart` file
with a JS interop extension with the intersection of all the dart:html
CSS property getters and setters from CssStyleDeclaration and
CssStyleDeclarationBase.
Change-Id: Ic616cdd5111eb169206a31c40e62356a7fb32150
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254561
Commit-Queue: Riley Porter <rileyporter@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
diff --git a/tools/dom/scripts/prototype_css_generator.py b/tools/dom/scripts/prototype_css_generator.py
new file mode 100644
index 0000000..7cf54af
--- /dev/null
+++ b/tools/dom/scripts/prototype_css_generator.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+"""Generates CssStyleDeclaration extension with all property getters and setters
+from css property definitions defined in WebKit."""
+
+import tempfile, os, re
+
+COMMENT_LINE_PREFIX = ' * '
+SOURCE_PATH = 'CSSPropertyNames.in'
+OUTPUT_FILE = 'prototype_css_properties.dart'
+
+# These are the properties that are supported on all Dart project supported
+# browsers as camelCased names on the CssStyleDeclaration.
+# Note that we do not use the MDN for compatibility info here.
+BROWSER_PATHS = [
+ 'cssProperties.CSS21.txt', # Remove when we have samples from all browsers.
+ 'cssProperties.ie9.txt',
+ 'cssProperties.ie10.txt',
+ 'cssProperties.ie11.txt',
+ 'cssProperties.ff36.txt',
+ 'cssProperties.chrome40.txt',
+ 'cssProperties.safari-7.1.3.txt',
+ 'cssProperties.mobileSafari-8.2.txt',
+ 'cssProperties.iPad4Air.onGoogleSites.txt',
+]
+
+# Supported annotations for any specific CSS properties.
+annotated = {
+ 'transition':
+ '''
+ @SupportedBrowser(SupportedBrowser.CHROME)
+ @SupportedBrowser(SupportedBrowser.FIREFOX)
+ @SupportedBrowser(SupportedBrowser.IE, '10')
+ @SupportedBrowser(SupportedBrowser.SAFARI)'''
+}
+
+
+class Error:
+
+ def __init__(self, message):
+ self.message = message
+
+ def __repr__(self):
+ return self.message
+
+
+def camelCaseName(name):
+ """Convert a CSS property name to a lowerCamelCase name."""
+ name = name.replace('-webkit-', '')
+ words = []
+ for word in name.split('-'):
+ if words:
+ words.append(word.title())
+ else:
+ words.append(word)
+ return ''.join(words)
+
+
+def dashifyName(camelName):
+
+ def fix(match):
+ return '-' + match.group(0).lower()
+
+ return re.sub(r'[A-Z]', fix, camelName)
+
+
+def isCommentLine(line):
+ return line.strip() == '' or line.startswith('#') or line.startswith('//')
+
+
+def readCssProperties(filename):
+ data = open(filename).readlines()
+ data = sorted([d.strip() for d in set(data) if not isCommentLine(d)])
+ return data
+
+
+def main():
+ data = open(SOURCE_PATH).readlines()
+ data = [d.strip() for d in data if not isCommentLine(d) and not '=' in d]
+
+ browser_props = [set(readCssProperties(file)) for file in BROWSER_PATHS]
+ universal_properties = set.intersection(*browser_props)
+ universal_properties = universal_properties.difference(['cssText'])
+ universal_properties = universal_properties.intersection(
+ list(map(camelCaseName, data)))
+
+ output_file = open(OUTPUT_FILE, 'w')
+ output_file.write("""
+/// Exposing all the extra CSS property getters and setters.
+part of 'dart:html_extensions';
+
+extension CssStyleDeclarationPropertiesExtension on html.CssStyleDeclaration {
+
+ // ##### Universal property getters and setters #####
+ """)
+
+ for camelName in sorted(universal_properties):
+ property = dashifyName(camelName)
+ output_file.write("""
+ /** Gets the value of "%s" */
+ String get %s => this._%s;
+
+ /** Sets the value of "%s" */
+ set %s(String? value) {
+ _%s = value == null ? '' : value;
+ }
+
+ @JS('%s')
+ external String get _%s;
+
+ @JS('%s')
+ external set _%s(String value);
+ """ % (property, camelName, camelName, property, camelName, camelName,
+ camelName, camelName, camelName, camelName))
+
+ output_file.write("""
+
+ // ##### Non-universal property getters and setters #####
+
+""")
+
+ property_lines = []
+
+ seen = set()
+ for prop in sorted(data, key=camelCaseName):
+ camel_case_name = camelCaseName(prop)
+ upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:]
+ css_name = prop.replace('-webkit-', '')
+ base_css_name = prop.replace('-webkit-', '')
+
+ if base_css_name in seen or base_css_name.startswith(
+ '-internal') or camel_case_name in universal_properties:
+ continue
+ seen.add(base_css_name)
+
+ comment = ' /** %s the value of "' + base_css_name + '" */'
+ property_lines.append('\n')
+ property_lines.append(comment % 'Gets')
+ if base_css_name in annotated:
+ property_lines.append(annotated[base_css_name])
+ property_lines.append("""
+ String get %s =>
+ getPropertyValue('%s');
+
+""" % (camel_case_name, css_name))
+
+ property_lines.append(comment % 'Sets')
+ if base_css_name in annotated:
+ property_lines.append(annotated[base_css_name])
+ property_lines.append("""
+ set %s(String value) {
+ setProperty('%s', value, '');
+ }
+""" % (camel_case_name, css_name))
+
+ output_file.write(''.join(property_lines))
+ output_file.write('}\n')
+ output_file.close()
+
+
+if __name__ == '__main__':
+ main()