a42c072017
CSSStyleDeclaration.getPropertyValue returns a non-nullable string. It will also return an empty string if the property is not found. Since getPropertyValue returns the value of the native getPropertyValue, the null check should be removed. Change-Id: I9846553d3f9fcd68cbd15b9c39d2104cab594b7a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136413 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Srujan Gaddam <srujzs@google.com>
320 lines
9.9 KiB
Python
320 lines
9.9 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Copyright (c) 2014, 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 template file from css property definitions
|
|
defined in WebKit."""
|
|
|
|
import tempfile, os, re
|
|
|
|
COMMENT_LINE_PREFIX = ' * '
|
|
# TODO(efortuna): Pull from DEPS so that we have latest css *in sync* with our
|
|
# Dartium. Then remove the checked in CSSPropertyNames.in.
|
|
SOURCE_PATH = 'CSSPropertyNames.in'
|
|
#SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in'
|
|
TEMPLATE_FILE = '../templates/html/impl/impl_CSSStyleDeclaration.darttemplate'
|
|
|
|
# These are the properties that are supported on all Dart project supported
|
|
# browsers as camelCased names on the CssStyleDeclaration.
|
|
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 GenerateCssTemplateFile():
|
|
data = open(SOURCE_PATH).readlines()
|
|
|
|
# filter CSSPropertyNames.in to only the properties
|
|
# TODO(efortuna): do we also want CSSPropertyNames.in?
|
|
data = [d.strip() for d in data if not isCommentLine(d) and not '=' in d]
|
|
|
|
browser_props = [readCssProperties(file) for file in BROWSER_PATHS]
|
|
universal_properties = reduce(lambda a, b: set(a).intersection(b),
|
|
browser_props)
|
|
universal_properties = universal_properties.difference(['cssText'])
|
|
universal_properties = universal_properties.intersection(
|
|
map(camelCaseName, data))
|
|
|
|
class_file = open(TEMPLATE_FILE, 'w')
|
|
|
|
class_file.write("""
|
|
// Copyright (c) 2014, 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.
|
|
|
|
// WARNING: DO NOT EDIT THIS TEMPLATE FILE.
|
|
// The template file was generated by scripts/css_code_generator.py
|
|
|
|
// Source of CSS properties:
|
|
// %s
|
|
|
|
part of $LIBRARYNAME;
|
|
""" % SOURCE_PATH)
|
|
|
|
class_file.write("""
|
|
$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME $EXTENDS with
|
|
$(CLASSNAME)Base $IMPLEMENTS {
|
|
factory $CLASSNAME() => new CssStyleDeclaration.css('');
|
|
|
|
factory $CLASSNAME.css(String css) {
|
|
final style = new DivElement().style;
|
|
style.cssText = css;
|
|
return style;
|
|
}
|
|
|
|
/// Returns the value of the property if the provided *CSS* property
|
|
/// name is supported on this element and if the value is set. Otherwise
|
|
/// returns an empty string.
|
|
///
|
|
/// Please note the property name uses camelCase, not-hyphens.
|
|
String getPropertyValue(String propertyName) {
|
|
return _getPropertyValueHelper(propertyName);
|
|
}
|
|
|
|
String _getPropertyValueHelper(String propertyName) {
|
|
return _getPropertyValue(_browserPropertyName(propertyName));
|
|
}
|
|
|
|
/**
|
|
* Returns true if the provided *CSS* property name is supported on this
|
|
* element.
|
|
*
|
|
* Please note the property name camelCase, not-hyphens. This
|
|
* method returns true if the property is accessible via an unprefixed _or_
|
|
* prefixed property.
|
|
*/
|
|
bool supportsProperty(String propertyName) {
|
|
return _supportsProperty(propertyName) ||
|
|
_supportsProperty(_camelCase("${Device.cssPrefix}$propertyName"));
|
|
}
|
|
|
|
bool _supportsProperty(String propertyName) {
|
|
return JS('bool', '# in #', propertyName, this);
|
|
}
|
|
|
|
|
|
void setProperty(String propertyName, String value,
|
|
[String$NULLABLE priority]) {
|
|
return _setPropertyHelper(_browserPropertyName(propertyName),
|
|
value, priority);
|
|
}
|
|
|
|
String _browserPropertyName(String propertyName) {
|
|
String$NULLABLE name = _readCache(propertyName);
|
|
if (name is String) return name;
|
|
name = _supportedBrowserPropertyName(propertyName);
|
|
_writeCache(propertyName, name);
|
|
return name;
|
|
}
|
|
|
|
String _supportedBrowserPropertyName(String propertyName) {
|
|
if (_supportsProperty(_camelCase(propertyName))) {
|
|
return propertyName;
|
|
}
|
|
var prefixed = "${Device.cssPrefix}$propertyName";
|
|
if (_supportsProperty(prefixed)) {
|
|
return prefixed;
|
|
}
|
|
// May be a CSS variable, just use it as provided.
|
|
return propertyName;
|
|
}
|
|
|
|
static final _propertyCache = JS('', '{}');
|
|
static String$NULLABLE _readCache(String key) =>
|
|
JS('String|Null', '#[#]', _propertyCache, key);
|
|
static void _writeCache(String key, String value) {
|
|
JS('void', '#[#] = #', _propertyCache, key, value);
|
|
}
|
|
|
|
static String _camelCase(String hyphenated) {
|
|
var replacedMs = JS('String', r'#.replace(/^-ms-/, "ms-")', hyphenated);
|
|
return JS(
|
|
'String',
|
|
r'#.replace(/-([\da-z])/ig,'
|
|
r'function(_, letter) { return letter.toUpperCase();})',
|
|
replacedMs);
|
|
}
|
|
|
|
void _setPropertyHelper(String propertyName, String$NULLABLE value,
|
|
[String$NULLABLE priority]) {
|
|
if (value == null) value = '';
|
|
if (priority == null) priority = '';
|
|
JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
|
|
}
|
|
|
|
/**
|
|
* Checks to see if CSS Transitions are supported.
|
|
*/
|
|
static bool get supportsTransitions {
|
|
return document.body.style.supportsProperty('transition');
|
|
}
|
|
$!MEMBERS
|
|
""")
|
|
|
|
for camelName in sorted(universal_properties):
|
|
property = dashifyName(camelName)
|
|
class_file.write("""
|
|
/** Gets the value of "%s" */
|
|
String get %s => this._%s;
|
|
|
|
/** Sets the value of "%s" */
|
|
set %s(String$NULLABLE value) {
|
|
_%s = value == null ? '' : value;
|
|
}
|
|
@Returns('String')
|
|
@JSName('%s')
|
|
String _%s;
|
|
""" % (property, camelName, camelName, property, camelName, camelName,
|
|
camelName, camelName))
|
|
|
|
class_file.write("""
|
|
}
|
|
|
|
class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
|
|
final Iterable<Element> _elementIterable;
|
|
Iterable<CssStyleDeclaration>$NULLABLE _elementCssStyleDeclarationSetIterable;
|
|
|
|
_CssStyleDeclarationSet(this._elementIterable) {
|
|
_elementCssStyleDeclarationSetIterable = new List.from(
|
|
_elementIterable).map((e) => e.style);
|
|
}
|
|
|
|
String getPropertyValue(String propertyName) =>
|
|
_elementCssStyleDeclarationSetIterable$NULLASSERT.first.getPropertyValue(
|
|
propertyName);
|
|
|
|
void setProperty(String propertyName, String value,
|
|
[String$NULLABLE priority]) {
|
|
_elementCssStyleDeclarationSetIterable$NULLASSERT.forEach((e) =>
|
|
e.setProperty(propertyName, value, priority));
|
|
}
|
|
|
|
""")
|
|
|
|
class_file.write("""
|
|
void _setAll(String propertyName, String$NULLABLE value) {
|
|
value = value == null ? '' : value;
|
|
for (Element element in _elementIterable) {
|
|
JS('void', '#.style[#] = #', element, propertyName, value);
|
|
}
|
|
}
|
|
""")
|
|
|
|
for camelName in sorted(universal_properties):
|
|
property = dashifyName(camelName)
|
|
class_file.write("""
|
|
/** Sets the value of "%s" */
|
|
set %s(String value) {
|
|
_setAll('%s', value);
|
|
}
|
|
""" % (property, camelName, camelName))
|
|
|
|
class_file.write("""
|
|
|
|
// Important note: CssStyleDeclarationSet does NOT implement every method
|
|
// available in CssStyleDeclaration. Some of the methods don't make so much
|
|
// sense in terms of having a resonable value to return when you're
|
|
// considering a list of Elements. You will need to manually add any of the
|
|
// items in the MEMBERS set if you want that functionality.
|
|
}
|
|
|
|
abstract class CssStyleDeclarationBase {
|
|
String getPropertyValue(String propertyName);
|
|
void setProperty(String propertyName, String value,
|
|
[String$NULLABLE priority]);
|
|
""")
|
|
|
|
class_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'):
|
|
continue
|
|
seen.add(base_css_name)
|
|
|
|
comment = ' /** %s the value of "' + base_css_name + '" */'
|
|
class_lines.append('\n')
|
|
class_lines.append(comment % 'Gets')
|
|
if base_css_name in annotated:
|
|
class_lines.append(annotated[base_css_name])
|
|
class_lines.append("""
|
|
String get %s =>
|
|
getPropertyValue('%s');
|
|
|
|
""" % (camel_case_name, css_name))
|
|
|
|
class_lines.append(comment % 'Sets')
|
|
if base_css_name in annotated:
|
|
class_lines.append(annotated[base_css_name])
|
|
class_lines.append("""
|
|
set %s(String value) {
|
|
setProperty('%s', value, '');
|
|
}
|
|
""" % (camel_case_name, css_name))
|
|
|
|
class_file.write(''.join(class_lines))
|
|
class_file.write('}\n')
|
|
class_file.close()
|