| Index: appengine/config_service/ui/bower_components/shadycss/src/style-properties.js
|
| diff --git a/appengine/config_service/ui/bower_components/shadycss/src/style-properties.js b/appengine/config_service/ui/bower_components/shadycss/src/style-properties.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7f72bda794afcd5bf34db6630787a1b6a0744c46
|
| --- /dev/null
|
| +++ b/appengine/config_service/ui/bower_components/shadycss/src/style-properties.js
|
| @@ -0,0 +1,604 @@
|
| +/**
|
| +@license
|
| +Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
| +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| +Code distributed by Google as part of the polymer project is also
|
| +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| +*/
|
| +
|
| +'use strict';
|
| +
|
| +import {removeCustomPropAssignment, StyleNode} from './css-parse.js' // eslint-disable-line no-unused-vars
|
| +import {nativeShadow} from './style-settings.js'
|
| +import StyleTransformer from './style-transformer.js'
|
| +import * as StyleUtil from './style-util.js'
|
| +import * as RX from './common-regex.js'
|
| +import StyleInfo from './style-info.js'
|
| +
|
| +// TODO: dedupe with shady
|
| +/**
|
| + * @const {function(string):boolean}
|
| + */
|
| +const matchesSelector = ((p) => p.matches || p.matchesSelector ||
|
| + p.mozMatchesSelector || p.msMatchesSelector ||
|
| +p.oMatchesSelector || p.webkitMatchesSelector)(window.Element.prototype);
|
| +
|
| +const IS_IE = navigator.userAgent.match('Trident');
|
| +
|
| +const XSCOPE_NAME = 'x-scope';
|
| +
|
| +class StyleProperties {
|
| + get XSCOPE_NAME() {
|
| + return XSCOPE_NAME;
|
| + }
|
| +/**
|
| + * decorates styles with rule info and returns an array of used style property names
|
| + *
|
| + * @param {StyleNode} rules
|
| + * @return {Array<string>}
|
| + */
|
| + decorateStyles(rules) {
|
| + let self = this, props = {}, keyframes = [], ruleIndex = 0;
|
| + StyleUtil.forEachRule(rules, function(rule) {
|
| + self.decorateRule(rule);
|
| + // mark in-order position of ast rule in styles block, used for cache key
|
| + rule.index = ruleIndex++;
|
| + self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
|
| + }, function onKeyframesRule(rule) {
|
| + keyframes.push(rule);
|
| + });
|
| + // Cache all found keyframes rules for later reference:
|
| + rules._keyframes = keyframes;
|
| + // return this list of property names *consumes* in these styles.
|
| + let names = [];
|
| + for (let i in props) {
|
| + names.push(i);
|
| + }
|
| + return names;
|
| + }
|
| +
|
| + // decorate a single rule with property info
|
| + decorateRule(rule) {
|
| + if (rule.propertyInfo) {
|
| + return rule.propertyInfo;
|
| + }
|
| + let info = {}, properties = {};
|
| + let hasProperties = this.collectProperties(rule, properties);
|
| + if (hasProperties) {
|
| + info.properties = properties;
|
| + // TODO(sorvell): workaround parser seeing mixins as additional rules
|
| + rule['rules'] = null;
|
| + }
|
| + info.cssText = this.collectCssText(rule);
|
| + rule.propertyInfo = info;
|
| + return info;
|
| + }
|
| +
|
| + // collects the custom properties from a rule's cssText
|
| + collectProperties(rule, properties) {
|
| + let info = rule.propertyInfo;
|
| + if (info) {
|
| + if (info.properties) {
|
| + Object.assign(properties, info.properties);
|
| + return true;
|
| + }
|
| + } else {
|
| + let m, rx = RX.VAR_ASSIGN;
|
| + let cssText = rule['parsedCssText'];
|
| + let value;
|
| + let any;
|
| + while ((m = rx.exec(cssText))) {
|
| + // note: group 2 is var, 3 is mixin
|
| + value = (m[2] || m[3]).trim();
|
| + // value of 'inherit' or 'unset' is equivalent to not setting the property here
|
| + if (value !== 'inherit' || value !== 'unset') {
|
| + properties[m[1].trim()] = value;
|
| + }
|
| + any = true;
|
| + }
|
| + return any;
|
| + }
|
| +
|
| + }
|
| +
|
| + // returns cssText of properties that consume variables/mixins
|
| + collectCssText(rule) {
|
| + return this.collectConsumingCssText(rule['parsedCssText']);
|
| + }
|
| +
|
| + // NOTE: we support consumption inside mixin assignment
|
| + // but not production, so strip out {...}
|
| + collectConsumingCssText(cssText) {
|
| + return cssText.replace(RX.BRACKETED, '')
|
| + .replace(RX.VAR_ASSIGN, '');
|
| + }
|
| +
|
| + collectPropertiesInCssText(cssText, props) {
|
| + let m;
|
| + while ((m = RX.VAR_CONSUMED.exec(cssText))) {
|
| + let name = m[1];
|
| + // This regex catches all variable names, and following non-whitespace char
|
| + // If next char is not ':', then variable is a consumer
|
| + if (m[2] !== ':') {
|
| + props[name] = true;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // turns custom properties into realized values.
|
| + reify(props) {
|
| + // big perf optimization here: reify only *own* properties
|
| + // since this object has __proto__ of the element's scope properties
|
| + let names = Object.getOwnPropertyNames(props);
|
| + for (let i=0, n; i < names.length; i++) {
|
| + n = names[i];
|
| + props[n] = this.valueForProperty(props[n], props);
|
| + }
|
| + }
|
| +
|
| + // given a property value, returns the reified value
|
| + // a property value may be:
|
| + // (1) a literal value like: red or 5px;
|
| + // (2) a variable value like: var(--a), var(--a, red), or var(--a, --b) or
|
| + // var(--a, var(--b));
|
| + // (3) a literal mixin value like { properties }. Each of these properties
|
| + // can have values that are: (a) literal, (b) variables, (c) @apply mixins.
|
| + valueForProperty(property, props) {
|
| + // case (1) default
|
| + // case (3) defines a mixin and we have to reify the internals
|
| + if (property) {
|
| + if (property.indexOf(';') >=0) {
|
| + property = this.valueForProperties(property, props);
|
| + } else {
|
| + // case (2) variable
|
| + let self = this;
|
| + let fn = function(prefix, value, fallback, suffix) {
|
| + if (!value) {
|
| + return prefix + suffix;
|
| + }
|
| + let propertyValue = self.valueForProperty(props[value], props);
|
| + // if value is "initial", then the variable should be treated as unset
|
| + if (!propertyValue || propertyValue === 'initial') {
|
| + // fallback may be --a or var(--a) or literal
|
| + propertyValue = self.valueForProperty(props[fallback] || fallback, props) ||
|
| + fallback;
|
| + } else if (propertyValue === 'apply-shim-inherit') {
|
| + // CSS build will replace `inherit` with `apply-shim-inherit`
|
| + // for use with native css variables.
|
| + // Since we have full control, we can use `inherit` directly.
|
| + propertyValue = 'inherit';
|
| + }
|
| + return prefix + (propertyValue || '') + suffix;
|
| + };
|
| + property = StyleUtil.processVariableAndFallback(property, fn);
|
| + }
|
| + }
|
| + return property && property.trim() || '';
|
| + }
|
| +
|
| + // note: we do not yet support mixin within mixin
|
| + valueForProperties(property, props) {
|
| + let parts = property.split(';');
|
| + for (let i=0, p, m; i<parts.length; i++) {
|
| + if ((p = parts[i])) {
|
| + RX.MIXIN_MATCH.lastIndex = 0;
|
| + m = RX.MIXIN_MATCH.exec(p);
|
| + if (m) {
|
| + p = this.valueForProperty(props[m[1]], props);
|
| + } else {
|
| + let colon = p.indexOf(':');
|
| + if (colon !== -1) {
|
| + let pp = p.substring(colon);
|
| + pp = pp.trim();
|
| + pp = this.valueForProperty(pp, props) || pp;
|
| + p = p.substring(0, colon) + pp;
|
| + }
|
| + }
|
| + parts[i] = (p && p.lastIndexOf(';') === p.length - 1) ?
|
| + // strip trailing ;
|
| + p.slice(0, -1) :
|
| + p || '';
|
| + }
|
| + }
|
| + return parts.join(';');
|
| + }
|
| +
|
| + applyProperties(rule, props) {
|
| + let output = '';
|
| + // dynamically added sheets may not be decorated so ensure they are.
|
| + if (!rule.propertyInfo) {
|
| + this.decorateRule(rule);
|
| + }
|
| + if (rule.propertyInfo.cssText) {
|
| + output = this.valueForProperties(rule.propertyInfo.cssText, props);
|
| + }
|
| + rule['cssText'] = output;
|
| + }
|
| +
|
| + // Apply keyframe transformations to the cssText of a given rule. The
|
| + // keyframeTransforms object is a map of keyframe names to transformer
|
| + // functions which take in cssText and spit out transformed cssText.
|
| + applyKeyframeTransforms(rule, keyframeTransforms) {
|
| + let input = rule['cssText'];
|
| + let output = rule['cssText'];
|
| + if (rule.hasAnimations == null) {
|
| + // Cache whether or not the rule has any animations to begin with:
|
| + rule.hasAnimations = RX.ANIMATION_MATCH.test(input);
|
| + }
|
| + // If there are no animations referenced, we can skip transforms:
|
| + if (rule.hasAnimations) {
|
| + let transform;
|
| + // If we haven't transformed this rule before, we iterate over all
|
| + // transforms:
|
| + if (rule.keyframeNamesToTransform == null) {
|
| + rule.keyframeNamesToTransform = [];
|
| + for (let keyframe in keyframeTransforms) {
|
| + transform = keyframeTransforms[keyframe];
|
| + output = transform(input);
|
| + // If the transform actually changed the CSS text, we cache the
|
| + // transform name for future use:
|
| + if (input !== output) {
|
| + input = output;
|
| + rule.keyframeNamesToTransform.push(keyframe);
|
| + }
|
| + }
|
| + } else {
|
| + // If we already have a list of keyframe names that apply to this
|
| + // rule, we apply only those keyframe name transforms:
|
| + for (let i = 0; i < rule.keyframeNamesToTransform.length; ++i) {
|
| + transform = keyframeTransforms[rule.keyframeNamesToTransform[i]];
|
| + input = transform(input);
|
| + }
|
| + output = input;
|
| + }
|
| + }
|
| + rule['cssText'] = output;
|
| + }
|
| +
|
| + // Test if the rules in these styles matches the given `element` and if so,
|
| + // collect any custom properties into `props`.
|
| + /**
|
| + * @param {StyleNode} rules
|
| + * @param {Element} element
|
| + */
|
| + propertyDataFromStyles(rules, element) {
|
| + let props = {}, self = this;
|
| + // generates a unique key for these matches
|
| + let o = [];
|
| + // note: active rules excludes non-matching @media rules
|
| + StyleUtil.forEachRule(rules, function(rule) {
|
| + // TODO(sorvell): we could trim the set of rules at declaration
|
| + // time to only include ones that have properties
|
| + if (!rule.propertyInfo) {
|
| + self.decorateRule(rule);
|
| + }
|
| + // match element against transformedSelector: selector may contain
|
| + // unwanted uniquification and parsedSelector does not directly match
|
| + // for :host selectors.
|
| + let selectorToMatch = rule.transformedSelector || rule['parsedSelector'];
|
| + if (element && rule.propertyInfo.properties && selectorToMatch) {
|
| + if (matchesSelector.call(element, selectorToMatch)) {
|
| + self.collectProperties(rule, props);
|
| + // produce numeric key for these matches for lookup
|
| + addToBitMask(rule.index, o);
|
| + }
|
| + }
|
| + }, null, true);
|
| + return {properties: props, key: o};
|
| + }
|
| +
|
| + /**
|
| + * @param {Element} scope
|
| + * @param {StyleNode} rule
|
| + * @param {string|undefined} cssBuild
|
| + * @param {function(Object)} callback
|
| + */
|
| + whenHostOrRootRule(scope, rule, cssBuild, callback) {
|
| + if (!rule.propertyInfo) {
|
| + this.decorateRule(rule);
|
| + }
|
| + if (!rule.propertyInfo.properties) {
|
| + return;
|
| + }
|
| + let {is, typeExtension} = StyleUtil.getIsExtends(scope);
|
| + let hostScope = is ?
|
| + StyleTransformer._calcHostScope(is, typeExtension) :
|
| + 'html';
|
| + let parsedSelector = rule['parsedSelector'];
|
| + let isRoot = (parsedSelector === ':host > *' || parsedSelector === 'html');
|
| + let isHost = parsedSelector.indexOf(':host') === 0 && !isRoot;
|
| + // build info is either in scope (when scope is an element) or in the style
|
| + // when scope is the default scope; note: this allows default scope to have
|
| + // mixed mode built and unbuilt styles.
|
| + if (cssBuild === 'shady') {
|
| + // :root -> x-foo > *.x-foo for elements and html for custom-style
|
| + isRoot = parsedSelector === (hostScope + ' > *.' + hostScope) || parsedSelector.indexOf('html') !== -1;
|
| + // :host -> x-foo for elements, but sub-rules have .x-foo in them
|
| + isHost = !isRoot && parsedSelector.indexOf(hostScope) === 0;
|
| + }
|
| + if (cssBuild === 'shadow') {
|
| + isRoot = parsedSelector === ':host > *' || parsedSelector === 'html';
|
| + isHost = isHost && !isRoot;
|
| + }
|
| + if (!isRoot && !isHost) {
|
| + return;
|
| + }
|
| + let selectorToMatch = hostScope;
|
| + if (isHost) {
|
| + // need to transform :host under ShadowDOM because `:host` does not work with `matches`
|
| + if (nativeShadow && !rule.transformedSelector) {
|
| + // transform :host into a matchable selector
|
| + rule.transformedSelector =
|
| + StyleTransformer._transformRuleCss(
|
| + rule,
|
| + StyleTransformer._transformComplexSelector,
|
| + StyleTransformer._calcElementScope(is),
|
| + hostScope
|
| + );
|
| + }
|
| + selectorToMatch = rule.transformedSelector || hostScope;
|
| + }
|
| + callback({
|
| + selector: selectorToMatch,
|
| + isHost: isHost,
|
| + isRoot: isRoot
|
| + });
|
| + }
|
| +/**
|
| + * @param {Element} scope
|
| + * @param {StyleNode} rules
|
| + * @return {Object}
|
| + */
|
| + hostAndRootPropertiesForScope(scope, rules) {
|
| + let hostProps = {}, rootProps = {}, self = this;
|
| + // note: active rules excludes non-matching @media rules
|
| + let cssBuild = rules && rules['__cssBuild'];
|
| + StyleUtil.forEachRule(rules, function(rule) {
|
| + // if scope is StyleDefaults, use _element for matchesSelector
|
| + self.whenHostOrRootRule(scope, rule, cssBuild, function(info) {
|
| + let element = scope._element || scope;
|
| + if (matchesSelector.call(element, info.selector)) {
|
| + if (info.isHost) {
|
| + self.collectProperties(rule, hostProps);
|
| + } else {
|
| + self.collectProperties(rule, rootProps);
|
| + }
|
| + }
|
| + });
|
| + }, null, true);
|
| + return {rootProps: rootProps, hostProps: hostProps};
|
| + }
|
| +
|
| + /**
|
| + * @param {Element} element
|
| + * @param {Object} properties
|
| + * @param {string} scopeSelector
|
| + */
|
| + transformStyles(element, properties, scopeSelector) {
|
| + let self = this;
|
| + let {is, typeExtension} = StyleUtil.getIsExtends(element);
|
| + let hostSelector = StyleTransformer
|
| + ._calcHostScope(is, typeExtension);
|
| + let rxHostSelector = element.extends ?
|
| + '\\' + hostSelector.slice(0, -1) + '\\]' :
|
| + hostSelector;
|
| + let hostRx = new RegExp(RX.HOST_PREFIX + rxHostSelector +
|
| + RX.HOST_SUFFIX);
|
| + let rules = StyleInfo.get(element).styleRules;
|
| + let keyframeTransforms =
|
| + this._elementKeyframeTransforms(element, rules, scopeSelector);
|
| + return StyleTransformer.elementStyles(element, rules, function(rule) {
|
| + self.applyProperties(rule, properties);
|
| + if (!nativeShadow &&
|
| + !StyleUtil.isKeyframesSelector(rule) &&
|
| + rule['cssText']) {
|
| + // NOTE: keyframe transforms only scope munge animation names, so it
|
| + // is not necessary to apply them in ShadowDOM.
|
| + self.applyKeyframeTransforms(rule, keyframeTransforms);
|
| + self._scopeSelector(rule, hostRx, hostSelector, scopeSelector);
|
| + }
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * @param {Element} element
|
| + * @param {StyleNode} rules
|
| + * @param {string} scopeSelector
|
| + * @return {Object}
|
| + */
|
| + _elementKeyframeTransforms(element, rules, scopeSelector) {
|
| + let keyframesRules = rules._keyframes;
|
| + let keyframeTransforms = {};
|
| + if (!nativeShadow && keyframesRules) {
|
| + // For non-ShadowDOM, we transform all known keyframes rules in
|
| + // advance for the current scope. This allows us to catch keyframes
|
| + // rules that appear anywhere in the stylesheet:
|
| + for (let i = 0, keyframesRule = keyframesRules[i];
|
| + i < keyframesRules.length;
|
| + keyframesRule = keyframesRules[++i]) {
|
| + this._scopeKeyframes(keyframesRule, scopeSelector);
|
| + keyframeTransforms[keyframesRule['keyframesName']] =
|
| + this._keyframesRuleTransformer(keyframesRule);
|
| + }
|
| + }
|
| + return keyframeTransforms;
|
| + }
|
| +
|
| + // Generate a factory for transforming a chunk of CSS text to handle a
|
| + // particular scoped keyframes rule.
|
| + /**
|
| + * @param {StyleNode} keyframesRule
|
| + * @return {function(string):string}
|
| + */
|
| + _keyframesRuleTransformer(keyframesRule) {
|
| + return function(cssText) {
|
| + return cssText.replace(
|
| + keyframesRule.keyframesNameRx,
|
| + keyframesRule.transformedKeyframesName);
|
| + };
|
| + }
|
| +
|
| +/**
|
| + * Transforms `@keyframes` names to be unique for the current host.
|
| + * Example: @keyframes foo-anim -> @keyframes foo-anim-x-foo-0
|
| + *
|
| + * @param {StyleNode} rule
|
| + * @param {string} scopeId
|
| + */
|
| + _scopeKeyframes(rule, scopeId) {
|
| + rule.keyframesNameRx = new RegExp(rule['keyframesName'], 'g');
|
| + rule.transformedKeyframesName = rule['keyframesName'] + '-' + scopeId;
|
| + rule.transformedSelector = rule.transformedSelector || rule['selector'];
|
| + rule['selector'] = rule.transformedSelector.replace(
|
| + rule['keyframesName'], rule.transformedKeyframesName);
|
| + }
|
| +
|
| + // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes):
|
| + // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo
|
| + // host selector: x-foo.wide -> .x-foo-42.wide
|
| + // note: we use only the scope class (.x-foo-42) and not the hostSelector
|
| + // (x-foo) to scope :host rules; this helps make property host rules
|
| + // have low specificity. They are overrideable by class selectors but,
|
| + // unfortunately, not by type selectors (e.g. overriding via
|
| + // `.special` is ok, but not by `x-foo`).
|
| + /**
|
| + * @param {StyleNode} rule
|
| + * @param {RegExp} hostRx
|
| + * @param {string} hostSelector
|
| + * @param {string} scopeId
|
| + */
|
| + _scopeSelector(rule, hostRx, hostSelector, scopeId) {
|
| + rule.transformedSelector = rule.transformedSelector || rule['selector'];
|
| + let selector = rule.transformedSelector;
|
| + let scope = '.' + scopeId;
|
| + let parts = selector.split(',');
|
| + for (let i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
|
| + parts[i] = p.match(hostRx) ?
|
| + p.replace(hostSelector, scope) :
|
| + scope + ' ' + p;
|
| + }
|
| + rule['selector'] = parts.join(',');
|
| + }
|
| +
|
| + /**
|
| + * @param {Element} element
|
| + * @param {string} selector
|
| + * @param {string} old
|
| + */
|
| + applyElementScopeSelector(element, selector, old) {
|
| + let c = element.getAttribute('class') || '';
|
| + let v = c;
|
| + if (old) {
|
| + v = c.replace(
|
| + new RegExp('\\s*' + XSCOPE_NAME + '\\s*' + old + '\\s*', 'g'), ' ');
|
| + }
|
| + v += (v ? ' ' : '') + XSCOPE_NAME + ' ' + selector;
|
| + if (c !== v) {
|
| + StyleUtil.setElementClassRaw(element, v);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {HTMLElement} element
|
| + * @param {Object} properties
|
| + * @param {string} selector
|
| + * @param {HTMLStyleElement} style
|
| + * @return {HTMLStyleElement}
|
| + */
|
| + applyElementStyle(element, properties, selector, style) {
|
| + // calculate cssText to apply
|
| + let cssText = style ? style.textContent || '' :
|
| + this.transformStyles(element, properties, selector);
|
| + // if shady and we have a cached style that is not style, decrement
|
| + let styleInfo = StyleInfo.get(element);
|
| + let s = styleInfo.customStyle;
|
| + if (s && !nativeShadow && (s !== style)) {
|
| + s['_useCount']--;
|
| + if (s['_useCount'] <= 0 && s.parentNode) {
|
| + s.parentNode.removeChild(s);
|
| + }
|
| + }
|
| + // apply styling always under native or if we generated style
|
| + // or the cached style is not in document(!)
|
| + if (nativeShadow) {
|
| + // update existing style only under native
|
| + if (styleInfo.customStyle) {
|
| + styleInfo.customStyle.textContent = cssText;
|
| + style = styleInfo.customStyle;
|
| + // otherwise, if we have css to apply, do so
|
| + } else if (cssText) {
|
| + // apply css after the scope style of the element to help with
|
| + // style precedence rules.
|
| + style = StyleUtil.applyCss(cssText, selector, element.shadowRoot,
|
| + styleInfo.placeholder);
|
| + }
|
| + } else {
|
| + // shady and no cache hit
|
| + if (!style) {
|
| + // apply css after the scope style of the element to help with
|
| + // style precedence rules.
|
| + if (cssText) {
|
| + style = StyleUtil.applyCss(cssText, selector, null,
|
| + styleInfo.placeholder);
|
| + }
|
| + // shady and cache hit but not in document
|
| + } else if (!style.parentNode) {
|
| + if (IS_IE && cssText.indexOf('@media') > -1) {
|
| + // @media rules may be stale in IE 10 and 11
|
| + // refresh the text content of the style to revalidate them.
|
| + style.textContent = cssText;
|
| + }
|
| + StyleUtil.applyStyle(style, null, styleInfo.placeholder);
|
| + }
|
| + }
|
| + // ensure this style is our custom style and increment its use count.
|
| + if (style) {
|
| + style['_useCount'] = style['_useCount'] || 0;
|
| + // increment use count if we changed styles
|
| + if (styleInfo.customStyle != style) {
|
| + style['_useCount']++;
|
| + }
|
| + styleInfo.customStyle = style;
|
| + }
|
| + return style;
|
| + }
|
| +
|
| + /**
|
| + * @param {Element} style
|
| + * @param {Object} properties
|
| + */
|
| + applyCustomStyle(style, properties) {
|
| + let rules = StyleUtil.rulesForStyle(/** @type {HTMLStyleElement} */(style));
|
| + let self = this;
|
| + style.textContent = StyleUtil.toCssText(rules, function(/** StyleNode */rule) {
|
| + let css = rule['cssText'] = rule['parsedCssText'];
|
| + if (rule.propertyInfo && rule.propertyInfo.cssText) {
|
| + // remove property assignments
|
| + // so next function isn't confused
|
| + // NOTE: we have 3 categories of css:
|
| + // (1) normal properties,
|
| + // (2) custom property assignments (--foo: red;),
|
| + // (3) custom property usage: border: var(--foo); @apply(--foo);
|
| + // In elements, 1 and 3 are separated for efficiency; here they
|
| + // are not and this makes this case unique.
|
| + css = removeCustomPropAssignment(/** @type {string} */(css));
|
| + // replace with reified properties, scenario is same as mixin
|
| + rule['cssText'] = self.valueForProperties(css, properties);
|
| + }
|
| + });
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {number} n
|
| + * @param {Array<number>} bits
|
| + */
|
| +function addToBitMask(n, bits) {
|
| + let o = parseInt(n / 32, 10);
|
| + let v = 1 << (n % 32);
|
| + bits[o] = (bits[o] || 0) | v;
|
| +}
|
| +
|
| +export default new StyleProperties();
|
|
|