| Index: appengine/config_service/ui/bower_components/shadycss/src/style-util.js
|
| diff --git a/appengine/config_service/ui/bower_components/shadycss/src/style-util.js b/appengine/config_service/ui/bower_components/shadycss/src/style-util.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d97f8c6c5814d886729c69ad375e37ef7e5b16dd
|
| --- /dev/null
|
| +++ b/appengine/config_service/ui/bower_components/shadycss/src/style-util.js
|
| @@ -0,0 +1,270 @@
|
| +/**
|
| +@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 {nativeShadow, nativeCssVariables} from './style-settings.js'
|
| +import {parse, stringify, types, StyleNode} from './css-parse.js' // eslint-disable-line no-unused-vars
|
| +import {MEDIA_MATCH} from './common-regex.js';
|
| +
|
| +/**
|
| + * @param {string|StyleNode} rules
|
| + * @param {function(StyleNode)=} callback
|
| + * @return {string}
|
| + */
|
| +export function toCssText (rules, callback) {
|
| + if (!rules) {
|
| + return '';
|
| + }
|
| + if (typeof rules === 'string') {
|
| + rules = parse(rules);
|
| + }
|
| + if (callback) {
|
| + forEachRule(rules, callback);
|
| + }
|
| + return stringify(rules, nativeCssVariables);
|
| +}
|
| +
|
| +/**
|
| + * @param {HTMLStyleElement} style
|
| + * @return {StyleNode}
|
| + */
|
| +export function rulesForStyle(style) {
|
| + if (!style['__cssRules'] && style.textContent) {
|
| + style['__cssRules'] = parse(style.textContent);
|
| + }
|
| + return style['__cssRules'] || null;
|
| +}
|
| +
|
| +// Tests if a rule is a keyframes selector, which looks almost exactly
|
| +// like a normal selector but is not (it has nothing to do with scoping
|
| +// for example).
|
| +/**
|
| + * @param {StyleNode} rule
|
| + * @return {boolean}
|
| + */
|
| +export function isKeyframesSelector(rule) {
|
| + return Boolean(rule['parent']) &&
|
| + rule['parent']['type'] === types.KEYFRAMES_RULE;
|
| +}
|
| +
|
| +/**
|
| + * @param {StyleNode} node
|
| + * @param {Function=} styleRuleCallback
|
| + * @param {Function=} keyframesRuleCallback
|
| + * @param {boolean=} onlyActiveRules
|
| + */
|
| +export function forEachRule(node, styleRuleCallback, keyframesRuleCallback, onlyActiveRules) {
|
| + if (!node) {
|
| + return;
|
| + }
|
| + let skipRules = false;
|
| + let type = node['type'];
|
| + if (onlyActiveRules) {
|
| + if (type === types.MEDIA_RULE) {
|
| + let matchMedia = node['selector'].match(MEDIA_MATCH);
|
| + if (matchMedia) {
|
| + // if rule is a non matching @media rule, skip subrules
|
| + if (!window.matchMedia(matchMedia[1]).matches) {
|
| + skipRules = true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (type === types.STYLE_RULE) {
|
| + styleRuleCallback(node);
|
| + } else if (keyframesRuleCallback &&
|
| + type === types.KEYFRAMES_RULE) {
|
| + keyframesRuleCallback(node);
|
| + } else if (type === types.MIXIN_RULE) {
|
| + skipRules = true;
|
| + }
|
| + let r$ = node['rules'];
|
| + if (r$ && !skipRules) {
|
| + for (let i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) {
|
| + forEachRule(r, styleRuleCallback, keyframesRuleCallback, onlyActiveRules);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// add a string of cssText to the document.
|
| +/**
|
| + * @param {string} cssText
|
| + * @param {string} moniker
|
| + * @param {Node} target
|
| + * @param {Node} contextNode
|
| + * @return {HTMLStyleElement}
|
| + */
|
| +export function applyCss(cssText, moniker, target, contextNode) {
|
| + let style = createScopeStyle(cssText, moniker);
|
| + applyStyle(style, target, contextNode);
|
| + return style;
|
| +}
|
| +
|
| +/**
|
| + * @param {string} cssText
|
| + * @param {string} moniker
|
| + * @return {HTMLStyleElement}
|
| + */
|
| +export function createScopeStyle(cssText, moniker) {
|
| + let style = /** @type {HTMLStyleElement} */(document.createElement('style'));
|
| + if (moniker) {
|
| + style.setAttribute('scope', moniker);
|
| + }
|
| + style.textContent = cssText;
|
| + return style;
|
| +}
|
| +
|
| +/**
|
| + * Track the position of the last added style for placing placeholders
|
| + * @type {Node}
|
| + */
|
| +let lastHeadApplyNode = null;
|
| +
|
| +// insert a comment node as a styling position placeholder.
|
| +/**
|
| + * @param {string} moniker
|
| + * @return {!Comment}
|
| + */
|
| +export function applyStylePlaceHolder(moniker) {
|
| + let placeHolder = document.createComment(' Shady DOM styles for ' +
|
| + moniker + ' ');
|
| + let after = lastHeadApplyNode ?
|
| + lastHeadApplyNode['nextSibling'] : null;
|
| + let scope = document.head;
|
| + scope.insertBefore(placeHolder, after || scope.firstChild);
|
| + lastHeadApplyNode = placeHolder;
|
| + return placeHolder;
|
| +}
|
| +
|
| +/**
|
| + * @param {HTMLStyleElement} style
|
| + * @param {?Node} target
|
| + * @param {?Node} contextNode
|
| + */
|
| +export function applyStyle(style, target, contextNode) {
|
| + target = target || document.head;
|
| + let after = (contextNode && contextNode.nextSibling) ||
|
| + target.firstChild;
|
| + target.insertBefore(style, after);
|
| + if (!lastHeadApplyNode) {
|
| + lastHeadApplyNode = style;
|
| + } else {
|
| + // only update lastHeadApplyNode if the new style is inserted after the old lastHeadApplyNode
|
| + let position = style.compareDocumentPosition(lastHeadApplyNode);
|
| + if (position === Node.DOCUMENT_POSITION_PRECEDING) {
|
| + lastHeadApplyNode = style;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {string} buildType
|
| + * @return {boolean}
|
| + */
|
| +export function isTargetedBuild(buildType) {
|
| + return nativeShadow ? buildType === 'shadow' : buildType === 'shady';
|
| +}
|
| +
|
| +/**
|
| + * @param {Element} element
|
| + * @return {?string}
|
| + */
|
| +export function getCssBuildType(element) {
|
| + return element.getAttribute('css-build');
|
| +}
|
| +
|
| +/**
|
| + * Walk from text[start] matching parens and
|
| + * returns position of the outer end paren
|
| + * @param {string} text
|
| + * @param {number} start
|
| + * @return {number}
|
| + */
|
| +function findMatchingParen(text, start) {
|
| + let level = 0;
|
| + for (let i=start, l=text.length; i < l; i++) {
|
| + if (text[i] === '(') {
|
| + level++;
|
| + } else if (text[i] === ')') {
|
| + if (--level === 0) {
|
| + return i;
|
| + }
|
| + }
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +/**
|
| + * @param {string} str
|
| + * @param {function(string, string, string, string)} callback
|
| + */
|
| +export function processVariableAndFallback(str, callback) {
|
| + // find 'var('
|
| + let start = str.indexOf('var(');
|
| + if (start === -1) {
|
| + // no var?, everything is prefix
|
| + return callback(str, '', '', '');
|
| + }
|
| + //${prefix}var(${inner})${suffix}
|
| + let end = findMatchingParen(str, start + 3);
|
| + let inner = str.substring(start + 4, end);
|
| + let prefix = str.substring(0, start);
|
| + // suffix may have other variables
|
| + let suffix = processVariableAndFallback(str.substring(end + 1), callback);
|
| + let comma = inner.indexOf(',');
|
| + // value and fallback args should be trimmed to match in property lookup
|
| + if (comma === -1) {
|
| + // variable, no fallback
|
| + return callback(prefix, inner.trim(), '', suffix);
|
| + }
|
| + // var(${value},${fallback})
|
| + let value = inner.substring(0, comma).trim();
|
| + let fallback = inner.substring(comma + 1).trim();
|
| + return callback(prefix, value, fallback, suffix);
|
| +}
|
| +
|
| +/**
|
| + * @param {Element} element
|
| + * @param {string} value
|
| + */
|
| +export function setElementClassRaw(element, value) {
|
| + // use native setAttribute provided by ShadyDOM when setAttribute is patched
|
| + if (nativeShadow) {
|
| + element.setAttribute('class', value);
|
| + } else {
|
| + window['ShadyDOM']['nativeMethods']['setAttribute'].call(element, 'class', value);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {Element | {is: string, extends: string}} element
|
| + * @return {{is: string, typeExtension: string}}
|
| + */
|
| +export function getIsExtends(element) {
|
| + let localName = element['localName'];
|
| + let is = '', typeExtension = '';
|
| + /*
|
| + NOTE: technically, this can be wrong for certain svg elements
|
| + with `-` in the name like `<font-face>`
|
| + */
|
| + if (localName) {
|
| + if (localName.indexOf('-') > -1) {
|
| + is = localName;
|
| + } else {
|
| + typeExtension = localName;
|
| + is = (element.getAttribute && element.getAttribute('is')) || '';
|
| + }
|
| + } else {
|
| + is = /** @type {?} */(element).is;
|
| + typeExtension = /** @type {?} */(element).extends;
|
| + }
|
| + return {is, typeExtension};
|
| +}
|
|
|