Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: appengine/config_service/ui/bower_components/shadycss/src/scoping-shim.js

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /**
2 @license
3 Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 */
10
11 'use strict';
12
13 import {parse, StyleNode} from './css-parse.js'
14 import {nativeShadow, nativeCssVariables} from './style-settings.js'
15 import StyleTransformer from './style-transformer.js'
16 import * as StyleUtil from './style-util.js'
17 import StyleProperties from './style-properties.js'
18 import placeholderMap from './style-placeholder.js'
19 import StyleInfo from './style-info.js'
20 import StyleCache from './style-cache.js'
21 import {flush as watcherFlush} from './document-watcher.js'
22 import templateMap from './template-map.js'
23 import * as ApplyShimUtils from './apply-shim-utils.js'
24 import documentWait from './document-wait.js'
25 import {updateNativeProperties, detectMixin} from './common-utils.js'
26 import {CustomStyleInterfaceInterface} from './custom-style-interface.js' //esli nt-disable-line no-unused-vars
27
28 /**
29 * @const {StyleCache}
30 */
31 const styleCache = new StyleCache();
32
33 export default class ScopingShim {
34 constructor() {
35 this._scopeCounter = {};
36 this._documentOwner = document.documentElement;
37 let ast = new StyleNode();
38 ast['rules'] = [];
39 this._documentOwnerStyleInfo = StyleInfo.set(this._documentOwner, new StyleI nfo(ast));
40 this._elementsHaveApplied = false;
41 this._applyShim = null;
42 /** @type {?CustomStyleInterfaceInterface} */
43 this._customStyleInterface = null;
44 documentWait(() => {
45 this._ensure();
46 });
47 }
48 flush() {
49 watcherFlush();
50 }
51 _generateScopeSelector(name) {
52 let id = this._scopeCounter[name] = (this._scopeCounter[name] || 0) + 1;
53 return `${name}-${id}`;
54 }
55 getStyleAst(style) {
56 return StyleUtil.rulesForStyle(style);
57 }
58 styleAstToString(ast) {
59 return StyleUtil.toCssText(ast);
60 }
61 _gatherStyles(template) {
62 let styles = template.content.querySelectorAll('style');
63 let cssText = [];
64 for (let i = 0; i < styles.length; i++) {
65 let s = styles[i];
66 cssText.push(s.textContent);
67 s.parentNode.removeChild(s);
68 }
69 return cssText.join('').trim();
70 }
71 _getCssBuild(template) {
72 let style = template.content.querySelector('style');
73 if (!style) {
74 return '';
75 }
76 return style.getAttribute('css-build') || '';
77 }
78 /**
79 * Prepare the styling and template for the given element type
80 *
81 * @param {HTMLTemplateElement} template
82 * @param {string} elementName
83 * @param {string=} typeExtension
84 */
85 prepareTemplate(template, elementName, typeExtension) {
86 if (template._prepared) {
87 return;
88 }
89 template._prepared = true;
90 template.name = elementName;
91 template.extends = typeExtension;
92 templateMap[elementName] = template;
93 let cssBuild = this._getCssBuild(template);
94 let cssText = this._gatherStyles(template);
95 let info = {
96 is: elementName,
97 extends: typeExtension,
98 __cssBuild: cssBuild,
99 };
100 if (!nativeShadow) {
101 StyleTransformer.dom(template.content, elementName);
102 }
103 // check if the styling has mixin definitions or uses
104 this._ensure();
105 let hasMixins = detectMixin(cssText)
106 let ast = parse(cssText);
107 // only run the applyshim transforms if there is a mixin involved
108 if (hasMixins && nativeCssVariables && this._applyShim) {
109 this._applyShim['transformRules'](ast, elementName);
110 }
111 template['_styleAst'] = ast;
112 template._cssBuild = cssBuild;
113
114 let ownPropertyNames = [];
115 if (!nativeCssVariables) {
116 ownPropertyNames = StyleProperties.decorateStyles(template['_styleAst'], i nfo);
117 }
118 if (!ownPropertyNames.length || nativeCssVariables) {
119 let root = nativeShadow ? template.content : null;
120 let placeholder = placeholderMap[elementName];
121 let style = this._generateStaticStyle(info, template['_styleAst'], root, p laceholder);
122 template._style = style;
123 }
124 template._ownPropertyNames = ownPropertyNames;
125 }
126 _generateStaticStyle(info, rules, shadowroot, placeholder) {
127 let cssText = StyleTransformer.elementStyles(info, rules);
128 if (cssText.length) {
129 return StyleUtil.applyCss(cssText, info.is, shadowroot, placeholder);
130 }
131 }
132 _prepareHost(host) {
133 let {is, typeExtension} = StyleUtil.getIsExtends(host);
134 let placeholder = placeholderMap[is];
135 let template = templateMap[is];
136 let ast;
137 let ownStylePropertyNames;
138 let cssBuild;
139 if (template) {
140 ast = template['_styleAst'];
141 ownStylePropertyNames = template._ownPropertyNames;
142 cssBuild = template._cssBuild;
143 }
144 return StyleInfo.set(host,
145 new StyleInfo(
146 ast,
147 placeholder,
148 ownStylePropertyNames,
149 is,
150 typeExtension,
151 cssBuild
152 )
153 );
154 }
155 _ensureApplyShim() {
156 if (this._applyShim) {
157 return;
158 } else if (window.ShadyCSS && window.ShadyCSS.ApplyShim) {
159 this._applyShim = window.ShadyCSS.ApplyShim;
160 this._applyShim['invalidCallback'] = ApplyShimUtils.invalidate;
161 }
162 }
163 _ensureCustomStyleInterface() {
164 if (this._customStyleInterface) {
165 return;
166 } else if (window.ShadyCSS && window.ShadyCSS.CustomStyleInterface) {
167 this._customStyleInterface = /** @type {!CustomStyleInterfaceInterface} */ (window.ShadyCSS.CustomStyleInterface);
168 /** @type {function(!HTMLStyleElement)} */
169 this._customStyleInterface['transformCallback'] = (style) => {this.transfo rmCustomStyleForDocument(style)};
170 this._customStyleInterface['validateCallback'] = () => {
171 requestAnimationFrame(() => {
172 if (this._customStyleInterface['enqueued'] || this._elementsHaveApplie d) {
173 this.flushCustomStyles();
174 }
175 })
176 };
177 }
178 }
179 _ensure() {
180 this._ensureApplyShim();
181 this._ensureCustomStyleInterface();
182 }
183 /**
184 * Flush and apply custom styles to document
185 */
186 flushCustomStyles() {
187 this._ensure();
188 if (!this._customStyleInterface) {
189 return;
190 }
191 let customStyles = this._customStyleInterface['processStyles']();
192 // early return if custom-styles don't need validation
193 if (!this._customStyleInterface['enqueued']) {
194 return;
195 }
196 if (!nativeCssVariables) {
197 this._updateProperties(this._documentOwner, this._documentOwnerStyleInfo);
198 this._applyCustomStyles(customStyles);
199 } else {
200 this._revalidateCustomStyleApplyShim(customStyles);
201 }
202 this._customStyleInterface['enqueued'] = false;
203 // if custom elements have upgraded and there are no native css variables, w e must recalculate the whole tree
204 if (this._elementsHaveApplied && !nativeCssVariables) {
205 this.styleDocument();
206 }
207 }
208 /**
209 * Apply styles for the given element
210 *
211 * @param {!HTMLElement} host
212 * @param {Object=} overrideProps
213 */
214 styleElement(host, overrideProps) {
215 let {is} = StyleUtil.getIsExtends(host);
216 let styleInfo = StyleInfo.get(host);
217 if (!styleInfo) {
218 styleInfo = this._prepareHost(host);
219 }
220 // Only trip the `elementsHaveApplied` flag if a node other that the root do cument has `applyStyle` called
221 if (!this._isRootOwner(host)) {
222 this._elementsHaveApplied = true;
223 }
224 if (overrideProps) {
225 styleInfo.overrideStyleProperties =
226 styleInfo.overrideStyleProperties || {};
227 Object.assign(styleInfo.overrideStyleProperties, overrideProps);
228 }
229 if (!nativeCssVariables) {
230 this._updateProperties(host, styleInfo);
231 if (styleInfo.ownStylePropertyNames && styleInfo.ownStylePropertyNames.len gth) {
232 this._applyStyleProperties(host, styleInfo);
233 }
234 } else {
235 if (styleInfo.overrideStyleProperties) {
236 updateNativeProperties(host, styleInfo.overrideStyleProperties);
237 }
238 let template = templateMap[is];
239 // bail early if there is no shadowroot for this element
240 if (!template && !this._isRootOwner(host)) {
241 return;
242 }
243 if (template && template._style && !ApplyShimUtils.templateIsValid(templat e)) {
244 // update template
245 if (!ApplyShimUtils.templateIsValidating(template)) {
246 this._ensure();
247 this._applyShim && this._applyShim['transformRules'](template['_styleA st'], is);
248 template._style.textContent = StyleTransformer.elementStyles(host, sty leInfo.styleRules);
249 ApplyShimUtils.startValidatingTemplate(template);
250 }
251 // update instance if native shadowdom
252 if (nativeShadow) {
253 let root = host.shadowRoot;
254 if (root) {
255 let style = root.querySelector('style');
256 style.textContent = StyleTransformer.elementStyles(host, styleInfo.s tyleRules);
257 }
258 }
259 styleInfo.styleRules = template['_styleAst'];
260 }
261 }
262 }
263 _styleOwnerForNode(node) {
264 let root = node.getRootNode();
265 let host = root.host;
266 if (host) {
267 if (StyleInfo.get(host)) {
268 return host;
269 } else {
270 return this._styleOwnerForNode(host);
271 }
272 }
273 return this._documentOwner;
274 }
275 _isRootOwner(node) {
276 return (node === this._documentOwner);
277 }
278 _applyStyleProperties(host, styleInfo) {
279 let is = StyleUtil.getIsExtends(host).is;
280 let cacheEntry = styleCache.fetch(is, styleInfo.styleProperties, styleInfo.o wnStylePropertyNames);
281 let cachedScopeSelector = cacheEntry && cacheEntry.scopeSelector;
282 let cachedStyle = cacheEntry ? cacheEntry.styleElement : null;
283 let oldScopeSelector = styleInfo.scopeSelector;
284 // only generate new scope if cached style is not found
285 styleInfo.scopeSelector = cachedScopeSelector || this._generateScopeSelector (is);
286 let style = StyleProperties.applyElementStyle(host, styleInfo.stylePropertie s, styleInfo.scopeSelector, cachedStyle);
287 if (!nativeShadow) {
288 StyleProperties.applyElementScopeSelector(host, styleInfo.scopeSelector, o ldScopeSelector);
289 }
290 if (!cacheEntry) {
291 styleCache.store(is, styleInfo.styleProperties, style, styleInfo.scopeSele ctor);
292 }
293 return style;
294 }
295 _updateProperties(host, styleInfo) {
296 let owner = this._styleOwnerForNode(host);
297 let ownerStyleInfo = StyleInfo.get(owner);
298 let ownerProperties = ownerStyleInfo.styleProperties;
299 let props = Object.create(ownerProperties || null);
300 let hostAndRootProps = StyleProperties.hostAndRootPropertiesForScope(host, s tyleInfo.styleRules);
301 let propertyData = StyleProperties.propertyDataFromStyles(ownerStyleInfo.sty leRules, host);
302 let propertiesMatchingHost = propertyData.properties
303 Object.assign(
304 props,
305 hostAndRootProps.hostProps,
306 propertiesMatchingHost,
307 hostAndRootProps.rootProps
308 );
309 this._mixinOverrideStyles(props, styleInfo.overrideStyleProperties);
310 StyleProperties.reify(props);
311 styleInfo.styleProperties = props;
312 }
313 _mixinOverrideStyles(props, overrides) {
314 for (let p in overrides) {
315 let v = overrides[p];
316 // skip override props if they are not truthy or 0
317 // in order to fall back to inherited values
318 if (v || v === 0) {
319 props[p] = v;
320 }
321 }
322 }
323 /**
324 * Update styles of the whole document
325 *
326 * @param {Object=} properties
327 */
328 styleDocument(properties) {
329 this.styleSubtree(this._documentOwner, properties);
330 }
331 /**
332 * Update styles of a subtree
333 *
334 * @param {!HTMLElement} host
335 * @param {Object=} properties
336 */
337 styleSubtree(host, properties) {
338 let root = host.shadowRoot;
339 if (root || this._isRootOwner(host)) {
340 this.styleElement(host, properties);
341 }
342 // process the shadowdom children of `host`
343 let shadowChildren = root && (root.children || root.childNodes);
344 if (shadowChildren) {
345 for (let i = 0; i < shadowChildren.length; i++) {
346 let c = /** @type {!HTMLElement} */(shadowChildren[i]);
347 this.styleSubtree(c);
348 }
349 } else {
350 // process the lightdom children of `host`
351 let children = host.children || host.childNodes;
352 if (children) {
353 for (let i = 0; i < children.length; i++) {
354 let c = /** @type {!HTMLElement} */(children[i]);
355 this.styleSubtree(c);
356 }
357 }
358 }
359 }
360 /* Custom Style operations */
361 _revalidateCustomStyleApplyShim(customStyles) {
362 for (let i = 0; i < customStyles.length; i++) {
363 let c = customStyles[i];
364 let s = this._customStyleInterface['getStyleForCustomStyle'](c);
365 if (s) {
366 this._revalidateApplyShim(s);
367 }
368 }
369 }
370 _applyCustomStyles(customStyles) {
371 for (let i = 0; i < customStyles.length; i++) {
372 let c = customStyles[i];
373 let s = this._customStyleInterface['getStyleForCustomStyle'](c);
374 if (s) {
375 StyleProperties.applyCustomStyle(s, this._documentOwnerStyleInfo.stylePr operties);
376 }
377 }
378 }
379 transformCustomStyleForDocument(style) {
380 let ast = StyleUtil.rulesForStyle(style);
381 StyleUtil.forEachRule(ast, (rule) => {
382 if (nativeShadow) {
383 StyleTransformer.normalizeRootSelector(rule);
384 } else {
385 StyleTransformer.documentRule(rule);
386 }
387 if (nativeCssVariables) {
388 this._ensure();
389 this._applyShim && this._applyShim['transformRule'](rule);
390 }
391 });
392 if (nativeCssVariables) {
393 style.textContent = StyleUtil.toCssText(ast);
394 } else {
395 this._documentOwnerStyleInfo.styleRules.rules.push(ast);
396 }
397 }
398 _revalidateApplyShim(style) {
399 if (nativeCssVariables && this._applyShim) {
400 let ast = StyleUtil.rulesForStyle(style);
401 this._ensure();
402 this._applyShim['transformRules'](ast);
403 style.textContent = StyleUtil.toCssText(ast);
404 }
405 }
406 getComputedStyleValue(element, property) {
407 let value;
408 if (!nativeCssVariables) {
409 // element is either a style host, or an ancestor of a style host
410 let styleInfo = StyleInfo.get(element) || StyleInfo.get(this._styleOwnerFo rNode(element));
411 value = styleInfo.styleProperties[property];
412 }
413 // fall back to the property value from the computed styling
414 value = value || window.getComputedStyle(element).getPropertyValue(property) ;
415 // trim whitespace that can come after the `:` in css
416 // example: padding: 2px -> " 2px"
417 return value ? value.trim() : '';
418 }
419 // given an element and a classString, replaces
420 // the element's class with the provided classString and adds
421 // any necessary ShadyCSS static and property based scoping selectors
422 setElementClass(element, classString) {
423 let root = element.getRootNode();
424 let classes = classString ? classString.split(/\s/) : [];
425 let scopeName = root.host && root.host.localName;
426 // If no scope, try to discover scope name from existing class.
427 // This can occur if, for example, a template stamped element that
428 // has been scoped is manipulated when not in a root.
429 if (!scopeName) {
430 var classAttr = element.getAttribute('class');
431 if (classAttr) {
432 let k$ = classAttr.split(/\s/);
433 for (let i=0; i < k$.length; i++) {
434 if (k$[i] === StyleTransformer.SCOPE_NAME) {
435 scopeName = k$[i+1];
436 break;
437 }
438 }
439 }
440 }
441 if (scopeName) {
442 classes.push(StyleTransformer.SCOPE_NAME, scopeName);
443 }
444 if (!nativeCssVariables) {
445 let styleInfo = StyleInfo.get(element);
446 if (styleInfo && styleInfo.scopeSelector) {
447 classes.push(StyleProperties.XSCOPE_NAME, styleInfo.scopeSelector);
448 }
449 }
450 StyleUtil.setElementClassRaw(element, classes.join(' '));
451 }
452 _styleInfoForNode(node) {
453 return StyleInfo.get(node);
454 }
455 }
456
457 /* exports */
458 ScopingShim.prototype['flush'] = ScopingShim.prototype.flush;
459 ScopingShim.prototype['prepareTemplate'] = ScopingShim.prototype.prepareTemplate ;
460 ScopingShim.prototype['styleElement'] = ScopingShim.prototype.styleElement;
461 ScopingShim.prototype['styleDocument'] = ScopingShim.prototype.styleDocument;
462 ScopingShim.prototype['styleSubtree'] = ScopingShim.prototype.styleSubtree;
463 ScopingShim.prototype['getComputedStyleValue'] = ScopingShim.prototype.getComput edStyleValue;
464 ScopingShim.prototype['setElementClass'] = ScopingShim.prototype.setElementClass ;
465 ScopingShim.prototype['_styleInfoForNode'] = ScopingShim.prototype._styleInfoFor Node;
466 ScopingShim.prototype['transformCustomStyleForDocument'] = ScopingShim.prototype .transformCustomStyleForDocument;
467 ScopingShim.prototype['getStyleAst'] = ScopingShim.prototype.getStyleAst;
468 ScopingShim.prototype['styleAstToString'] = ScopingShim.prototype.styleAstToStri ng;
469 ScopingShim.prototype['flushCustomStyles'] = ScopingShim.prototype.flushCustomSt yles;
470 Object.defineProperties(ScopingShim.prototype, {
471 'nativeShadow': {
472 get() {
473 return nativeShadow;
474 }
475 },
476 'nativeCss': {
477 get() {
478 return nativeCssVariables;
479 }
480 }
481 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698