| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | import {ConstantPool} from '../../constant_pool'; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  | import {AttributeMarker} from '../../core'; | 
					
						
							| 
									
										
										
										
											2019-09-09 13:14:26 -07:00
										 |  |  | import {AST, ASTWithSource, BindingPipe, BindingType, Interpolation} from '../../expression_parser/ast'; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | import * as o from '../../output/output_ast'; | 
					
						
							|  |  |  | import {ParseSourceSpan} from '../../parse_util'; | 
					
						
							| 
									
										
										
										
											2019-04-22 10:28:59 +02:00
										 |  |  | import {isEmptyExpression} from '../../template_parser/template_parser'; | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  | import {error} from '../../util'; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | import * as t from '../r3_ast'; | 
					
						
							|  |  |  | import {Identifiers as R3} from '../r3_identifiers'; | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  | import {hyphenate, parse as parseStyle} from './style_parser'; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | import {ValueConverter} from './template'; | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  | import {getInterpolationArgsLength} from './util'; | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  | const IMPORTANT_FLAG = '!important'; | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * A styling expression summary that is to be processed by the compiler | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  | export interface StylingInstruction { | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   sourceSpan: ParseSourceSpan|null; | 
					
						
							|  |  |  |   reference: o.ExternalReference; | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |   allocateBindingSlots: number; | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   supportsInterpolation?: boolean; | 
					
						
							|  |  |  |   params: ((convertFn: (value: any) => o.Expression | o.Expression[]) => o.Expression[]); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * An internal record of the input data for a styling binding | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | interface BoundStylingEntry { | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |   hasOverrideFlag: boolean; | 
					
						
							|  |  |  |   name: string|null; | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   unit: string|null; | 
					
						
							|  |  |  |   sourceSpan: ParseSourceSpan; | 
					
						
							|  |  |  |   value: AST; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |  * Produces creation/update instructions for all styling bindings (class and style) | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |  * It also produces the creation instruction to register all initial styling values | 
					
						
							|  |  |  |  * (which are all the static class="..." and style="..." attribute values that exist | 
					
						
							|  |  |  |  * on an element within a template). | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |  * The builder class below handles producing instructions for the following cases: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Static style/class attributes (style="..." and class="...") | 
					
						
							|  |  |  |  * - Dynamic style/class map bindings ([style]="map" and [class]="map|string") | 
					
						
							|  |  |  |  * - Dynamic style/class property bindings ([style.prop]="exp" and [class.name]="exp") | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Due to the complex relationship of all of these cases, the instructions generated | 
					
						
							|  |  |  |  * for these attributes/properties/bindings must be done so in the correct order. The | 
					
						
							|  |  |  |  * order which these must be generated is as follows: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * if (createMode) { | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |  *   styling(...) | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |  * } | 
					
						
							|  |  |  |  * if (updateMode) { | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |  *   styleMap(...) | 
					
						
							|  |  |  |  *   classMap(...) | 
					
						
							|  |  |  |  *   styleProp(...) | 
					
						
							|  |  |  |  *   classProp(...) | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |  * } | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |  * The creation/update methods within the builder class produce these instructions. | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | export class StylingBuilder { | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** Whether or not there are any static styling values present */ | 
					
						
							|  |  |  |   private _hasInitialValues = false; | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    *  Whether or not there are any styling bindings present | 
					
						
							|  |  |  |    *  (i.e. `[style]`, `[class]`, `[style.prop]` or `[class.name]`) | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |   public hasBindings = false; | 
					
						
							| 
									
										
										
										
											2019-09-09 13:14:26 -07:00
										 |  |  |   public hasBindingsWithPipes = false; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** the input for [class] (if it exists) */ | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   private _classMapInput: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** the input for [style] (if it exists) */ | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   private _styleMapInput: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** an array of each [style.prop] input */ | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   private _singleStyleInputs: BoundStylingEntry[]|null = null; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** an array of each [class.name] input */ | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   private _singleClassInputs: BoundStylingEntry[]|null = null; | 
					
						
							|  |  |  |   private _lastStylingInput: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |   private _firstStylingInput: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // maps are used instead of hash maps because a Map will
 | 
					
						
							|  |  |  |   // retain the ordering of the keys
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Represents the location of each style binding in the template | 
					
						
							|  |  |  |    * (e.g. `<div [style.width]="w" [style.height]="h">` implies | 
					
						
							|  |  |  |    * that `width=0` and `height=1`) | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   private _stylesIndex = new Map<string, number>(); | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Represents the location of each class binding in the template | 
					
						
							|  |  |  |    * (e.g. `<div [class.big]="b" [class.hidden]="h">` implies | 
					
						
							|  |  |  |    * that `big=0` and `hidden=1`) | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   private _classesIndex = new Map<string, number>(); | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   private _initialStyleValues: string[] = []; | 
					
						
							|  |  |  |   private _initialClassValues: string[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // certain style properties ALWAYS need sanitization
 | 
					
						
							|  |  |  |   // this is checked each time new styles are encountered
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   private _useDefaultSanitizer = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 15:20:19 -08:00
										 |  |  |   constructor(private _elementIndexExpr: o.Expression, private _directiveExpr: o.Expression|null) {} | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Registers a given input to the styling builder to be later used when producing AOT code. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The code below will only accept the input if it is somehow tied to styling (whether it be | 
					
						
							|  |  |  |    * style/class bindings or static style/class attributes). | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   registerBoundInput(input: t.BoundAttribute): boolean { | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     // [attr.style] or [attr.class] are skipped in the code below,
 | 
					
						
							|  |  |  |     // they should not be treated as styling-based bindings since
 | 
					
						
							|  |  |  |     // they are intended to be written directly to the attr and
 | 
					
						
							|  |  |  |     // will therefore skip all style/class resolution that is present
 | 
					
						
							|  |  |  |     // with style="", [style]="" and [style.prop]="", class="",
 | 
					
						
							|  |  |  |     // [class.prop]="". [class]="" assignments
 | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     let binding: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     let name = input.name; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     switch (input.type) { | 
					
						
							|  |  |  |       case BindingType.Property: | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |         binding = this.registerInputBasedOnName(name, input.value, input.sourceSpan); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |       case BindingType.Style: | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |         binding = this.registerStyleInput(name, false, input.value, input.sourceSpan, input.unit); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |       case BindingType.Class: | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |         binding = this.registerClassInput(name, false, input.value, input.sourceSpan); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     return binding ? true : false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |   registerInputBasedOnName(name: string, expression: AST, sourceSpan: ParseSourceSpan) { | 
					
						
							|  |  |  |     let binding: BoundStylingEntry|null = null; | 
					
						
							| 
									
										
										
										
											2019-08-30 20:19:39 +02:00
										 |  |  |     const prefix = name.substring(0, 6); | 
					
						
							|  |  |  |     const isStyle = name === 'style' || prefix === 'style.' || prefix === 'style!'; | 
					
						
							|  |  |  |     const isClass = !isStyle && | 
					
						
							|  |  |  |         (name === 'class' || name === 'className' || prefix === 'class.' || prefix === 'class!'); | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     if (isStyle || isClass) { | 
					
						
							|  |  |  |       const isMapBased = name.charAt(5) !== '.';         // style.prop or class.prop makes this a no
 | 
					
						
							|  |  |  |       const property = name.substr(isMapBased ? 5 : 6);  // the dot explains why there's a +1
 | 
					
						
							|  |  |  |       if (isStyle) { | 
					
						
							|  |  |  |         binding = this.registerStyleInput(property, isMapBased, expression, sourceSpan); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         binding = this.registerClassInput(property, isMapBased, expression, sourceSpan); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return binding; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |   registerStyleInput( | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |       name: string, isMapBased: boolean, value: AST, sourceSpan: ParseSourceSpan, | 
					
						
							| 
									
										
										
										
											2019-04-22 10:28:59 +02:00
										 |  |  |       unit?: string|null): BoundStylingEntry|null { | 
					
						
							|  |  |  |     if (isEmptyExpression(value)) { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  |     name = normalizePropName(name); | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     const {property, hasOverrideFlag, unit: bindingUnit} = parseProperty(name); | 
					
						
							|  |  |  |     const entry: BoundStylingEntry = { | 
					
						
							|  |  |  |       name: property, | 
					
						
							|  |  |  |       unit: unit || bindingUnit, value, sourceSpan, hasOverrideFlag | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     if (isMapBased) { | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |       this._useDefaultSanitizer = true; | 
					
						
							|  |  |  |       this._styleMapInput = entry; | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       (this._singleStyleInputs = this._singleStyleInputs || []).push(entry); | 
					
						
							|  |  |  |       this._useDefaultSanitizer = this._useDefaultSanitizer || isStyleSanitizable(name); | 
					
						
							|  |  |  |       registerIntoMap(this._stylesIndex, property); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     this._lastStylingInput = entry; | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |     this._firstStylingInput = this._firstStylingInput || entry; | 
					
						
							| 
									
										
										
										
											2019-09-09 13:14:26 -07:00
										 |  |  |     this._checkForPipes(value); | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |     this.hasBindings = true; | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     return entry; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |   registerClassInput(name: string, isMapBased: boolean, value: AST, sourceSpan: ParseSourceSpan): | 
					
						
							| 
									
										
										
										
											2019-04-22 10:28:59 +02:00
										 |  |  |       BoundStylingEntry|null { | 
					
						
							|  |  |  |     if (isEmptyExpression(value)) { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     const {property, hasOverrideFlag} = parseProperty(name); | 
					
						
							|  |  |  |     const entry: | 
					
						
							|  |  |  |         BoundStylingEntry = {name: property, value, sourceSpan, hasOverrideFlag, unit: null}; | 
					
						
							|  |  |  |     if (isMapBased) { | 
					
						
							| 
									
										
										
										
											2019-10-04 19:25:18 -07:00
										 |  |  |       if (this._classMapInput) { | 
					
						
							|  |  |  |         throw new Error( | 
					
						
							|  |  |  |             '[class] and [className] bindings cannot be used on the same element simultaneously'); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |       this._classMapInput = entry; | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       (this._singleClassInputs = this._singleClassInputs || []).push(entry); | 
					
						
							|  |  |  |       registerIntoMap(this._classesIndex, property); | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     this._lastStylingInput = entry; | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |     this._firstStylingInput = this._firstStylingInput || entry; | 
					
						
							| 
									
										
										
										
											2019-09-09 13:14:26 -07:00
										 |  |  |     this._checkForPipes(value); | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |     this.hasBindings = true; | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  |     return entry; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 13:14:26 -07:00
										 |  |  |   private _checkForPipes(value: AST) { | 
					
						
							|  |  |  |     if ((value instanceof ASTWithSource) && (value.ast instanceof BindingPipe)) { | 
					
						
							|  |  |  |       this.hasBindingsWithPipes = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Registers the element's static style string value to the builder. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param value the style string (e.g. `width:100px; height:200px;`) | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   registerStyleAttr(value: string) { | 
					
						
							|  |  |  |     this._initialStyleValues = parseStyle(value); | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |     this._hasInitialValues = true; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Registers the element's static class string value to the builder. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param value the className string (e.g. `disabled gold zoom`) | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   registerClassAttr(value: string) { | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |     this._initialClassValues = value.trim().split(/\s+/g); | 
					
						
							|  |  |  |     this._hasInitialValues = true; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Appends all styling-related expressions to the provided attrs array. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param attrs an existing array where each of the styling expressions | 
					
						
							|  |  |  |    * will be inserted into. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   populateInitialStylingAttrs(attrs: o.Expression[]): void { | 
					
						
							|  |  |  |     // [CLASS_MARKER, 'foo', 'bar', 'baz' ...]
 | 
					
						
							|  |  |  |     if (this._initialClassValues.length) { | 
					
						
							|  |  |  |       attrs.push(o.literal(AttributeMarker.Classes)); | 
					
						
							|  |  |  |       for (let i = 0; i < this._initialClassValues.length; i++) { | 
					
						
							|  |  |  |         attrs.push(o.literal(this._initialClassValues[i])); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |     // [STYLE_MARKER, 'width', '200px', 'height', '100px', ...]
 | 
					
						
							|  |  |  |     if (this._initialStyleValues.length) { | 
					
						
							|  |  |  |       attrs.push(o.literal(AttributeMarker.Styles)); | 
					
						
							|  |  |  |       for (let i = 0; i < this._initialStyleValues.length; i += 2) { | 
					
						
							|  |  |  |         attrs.push( | 
					
						
							|  |  |  |             o.literal(this._initialStyleValues[i]), o.literal(this._initialStyleValues[i + 1])); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Builds an instruction with all the expressions and parameters for `elementHostAttrs`. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The instruction generation code below is used for producing the AOT statement code which is | 
					
						
							| 
									
										
										
										
											2019-01-11 14:03:37 -08:00
										 |  |  |    * responsible for registering initial styles (within a directive hostBindings' creation block), | 
					
						
							|  |  |  |    * as well as any of the provided attribute values, to the directive host element. | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-01-11 14:03:37 -08:00
										 |  |  |   buildHostAttrsInstruction( | 
					
						
							|  |  |  |       sourceSpan: ParseSourceSpan|null, attrs: o.Expression[], | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       constantPool: ConstantPool): StylingInstruction|null { | 
					
						
							| 
									
										
										
										
											2019-01-11 14:03:37 -08:00
										 |  |  |     if (this._directiveExpr && (attrs.length || this._hasInitialValues)) { | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |       return { | 
					
						
							|  |  |  |         sourceSpan, | 
					
						
							|  |  |  |         reference: R3.elementHostAttrs, | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |         allocateBindingSlots: 0, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |         params: () => { | 
					
						
							| 
									
										
										
										
											2019-05-08 10:18:33 -07:00
										 |  |  |           // params => elementHostAttrs(attrs)
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |           this.populateInitialStylingAttrs(attrs); | 
					
						
							| 
									
										
										
										
											2019-02-27 16:54:37 -08:00
										 |  |  |           const attrArray = !attrs.some(attr => attr instanceof o.WrappedNodeExpr) ? | 
					
						
							|  |  |  |               getConstantLiteralFromArray(constantPool, attrs) : | 
					
						
							|  |  |  |               o.literalArr(attrs); | 
					
						
							| 
									
										
										
										
											2019-03-15 13:45:08 -07:00
										 |  |  |           return [attrArray]; | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |    * Builds an instruction with all the expressions and parameters for `classMap`. | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |    * The instruction data will contain all expressions for `classMap` to function | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |    * which includes the `[class]` expression params. | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   buildClassMapInstruction(valueConverter: ValueConverter): StylingInstruction|null { | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     if (this._classMapInput) { | 
					
						
							|  |  |  |       return this._buildMapBasedInstruction(valueConverter, true, this._classMapInput); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |    * Builds an instruction with all the expressions and parameters for `styleMap`. | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |    * The instruction data will contain all expressions for `styleMap` to function | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |    * which includes the `[style]` expression params. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   buildStyleMapInstruction(valueConverter: ValueConverter): StylingInstruction|null { | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     if (this._styleMapInput) { | 
					
						
							|  |  |  |       return this._buildMapBasedInstruction(valueConverter, false, this._styleMapInput); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-03-15 13:45:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |   private _buildMapBasedInstruction( | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       valueConverter: ValueConverter, isClassBased: boolean, | 
					
						
							|  |  |  |       stylingInput: BoundStylingEntry): StylingInstruction { | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  |     // each styling binding value is stored in the LView
 | 
					
						
							|  |  |  |     let totalBindingSlotsRequired = 1; | 
					
						
							| 
									
										
										
										
											2019-03-15 13:45:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     // these values must be outside of the update block so that they can
 | 
					
						
							|  |  |  |     // be evaluated (the AST visit call) during creation time so that any
 | 
					
						
							|  |  |  |     // pipes can be picked up in time before the template is built
 | 
					
						
							|  |  |  |     const mapValue = stylingInput.value.visit(valueConverter); | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |     let reference: o.ExternalReference; | 
					
						
							|  |  |  |     if (mapValue instanceof Interpolation && isClassBased) { | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |       totalBindingSlotsRequired += mapValue.expressions.length; | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       reference = getClassMapInterpolationExpression(mapValue); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       reference = isClassBased ? R3.classMap : R3.styleMap; | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-15 13:45:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     return { | 
					
						
							|  |  |  |       sourceSpan: stylingInput.sourceSpan, | 
					
						
							|  |  |  |       reference, | 
					
						
							|  |  |  |       allocateBindingSlots: totalBindingSlotsRequired, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       supportsInterpolation: isClassBased, | 
					
						
							|  |  |  |       params: (convertFn: (value: any) => o.Expression | o.Expression[]) => { | 
					
						
							|  |  |  |         const convertResult = convertFn(mapValue); | 
					
						
							|  |  |  |         return Array.isArray(convertResult) ? convertResult : [convertResult]; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   private _buildSingleInputs( | 
					
						
							| 
									
										
										
										
											2019-05-07 14:02:11 -07:00
										 |  |  |       reference: o.ExternalReference, inputs: BoundStylingEntry[], mapIndex: Map<string, number>, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       allowUnits: boolean, valueConverter: ValueConverter, | 
					
						
							|  |  |  |       getInterpolationExpressionFn?: (value: Interpolation) => o.ExternalReference): | 
					
						
							|  |  |  |       StylingInstruction[] { | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |     let totalBindingSlotsRequired = 0; | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     return inputs.map(input => { | 
					
						
							|  |  |  |       const value = input.value.visit(valueConverter); | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // each styling binding value is stored in the LView
 | 
					
						
							|  |  |  |       let totalBindingSlotsRequired = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       if (value instanceof Interpolation) { | 
					
						
							|  |  |  |         totalBindingSlotsRequired += value.expressions.length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (getInterpolationExpressionFn) { | 
					
						
							|  |  |  |           reference = getInterpolationExpressionFn(value); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |       return { | 
					
						
							|  |  |  |         sourceSpan: input.sourceSpan, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |         supportsInterpolation: !!getInterpolationExpressionFn, | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |         allocateBindingSlots: totalBindingSlotsRequired, reference, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |         params: (convertFn: (value: any) => o.Expression | o.Expression[]) => { | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  |           // params => stylingProp(propName, value)
 | 
					
						
							|  |  |  |           const params: o.Expression[] = []; | 
					
						
							|  |  |  |           params.push(o.literal(input.name)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |           const convertResult = convertFn(value); | 
					
						
							|  |  |  |           if (Array.isArray(convertResult)) { | 
					
						
							|  |  |  |             params.push(...convertResult); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             params.push(convertResult); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-11-16 15:22:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  |           if (allowUnits && input.unit) { | 
					
						
							|  |  |  |             params.push(o.literal(input.unit)); | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |           return params; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   private _buildClassInputs(valueConverter: ValueConverter): StylingInstruction[] { | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     if (this._singleClassInputs) { | 
					
						
							|  |  |  |       return this._buildSingleInputs( | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |           R3.classProp, this._singleClassInputs, this._classesIndex, false, valueConverter); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return []; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   private _buildStyleInputs(valueConverter: ValueConverter): StylingInstruction[] { | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     if (this._singleStyleInputs) { | 
					
						
							|  |  |  |       return this._buildSingleInputs( | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |           R3.styleProp, this._singleStyleInputs, this._stylesIndex, true, valueConverter, | 
					
						
							|  |  |  |           getStylePropInterpolationExpression); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return []; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |   private _buildSanitizerFn(): StylingInstruction { | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |     return { | 
					
						
							|  |  |  |       sourceSpan: this._firstStylingInput ? this._firstStylingInput.sourceSpan : null, | 
					
						
							|  |  |  |       reference: R3.styleSanitizer, | 
					
						
							|  |  |  |       allocateBindingSlots: 0, | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |       params: () => [o.importExpr(R3.defaultStyleSanitizer)] | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Constructs all instructions which contain the expressions that will be placed | 
					
						
							|  |  |  |    * into the update block of a template function or a directive hostBindings function. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |   buildUpdateLevelInstructions(valueConverter: ValueConverter) { | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  |     const instructions: StylingInstruction[] = []; | 
					
						
							| 
									
										
										
										
											2019-01-16 11:11:33 -08:00
										 |  |  |     if (this.hasBindings) { | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  |       if (this._useDefaultSanitizer) { | 
					
						
							| 
									
										
										
										
											2019-05-24 13:49:57 -07:00
										 |  |  |         instructions.push(this._buildSanitizerFn()); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |       const styleMapInstruction = this.buildStyleMapInstruction(valueConverter); | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |       if (styleMapInstruction) { | 
					
						
							|  |  |  |         instructions.push(styleMapInstruction); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-05-08 11:26:40 -07:00
										 |  |  |       const classMapInstruction = this.buildClassMapInstruction(valueConverter); | 
					
						
							| 
									
										
										
										
											2019-05-06 17:44:03 -06:00
										 |  |  |       if (classMapInstruction) { | 
					
						
							|  |  |  |         instructions.push(classMapInstruction); | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |       instructions.push(...this._buildStyleInputs(valueConverter)); | 
					
						
							|  |  |  |       instructions.push(...this._buildClassInputs(valueConverter)); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  |     return instructions; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function registerIntoMap(map: Map<string, number>, key: string) { | 
					
						
							|  |  |  |   if (!map.has(key)) { | 
					
						
							|  |  |  |     map.set(key, map.size); | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 18:03:32 -08:00
										 |  |  | function isStyleSanitizable(prop: string): boolean { | 
					
						
							| 
									
										
										
										
											2019-05-08 09:27:44 -04:00
										 |  |  |   // Note that browsers support both the dash case and
 | 
					
						
							|  |  |  |   // camel case property names when setting through JS.
 | 
					
						
							|  |  |  |   return prop === 'background-image' || prop === 'backgroundImage' || prop === 'background' || | 
					
						
							|  |  |  |       prop === 'border-image' || prop === 'borderImage' || prop === 'filter' || | 
					
						
							|  |  |  |       prop === 'list-style' || prop === 'listStyle' || prop === 'list-style-image' || | 
					
						
							| 
									
										
										
										
											2019-05-15 20:24:55 +02:00
										 |  |  |       prop === 'listStyleImage' || prop === 'clip-path' || prop === 'clipPath'; | 
					
						
							| 
									
										
										
										
											2018-06-19 12:45:00 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Simple helper function to either provide the constant literal that will house the value | 
					
						
							|  |  |  |  * here or a null value if the provided values are empty. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function getConstantLiteralFromArray( | 
					
						
							|  |  |  |     constantPool: ConstantPool, values: o.Expression[]): o.Expression { | 
					
						
							|  |  |  |   return values.length ? constantPool.getConstLiteral(o.literalArr(values), true) : o.NULL_EXPR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Simple helper function that adds a parameter or does nothing at all depending on the provided | 
					
						
							|  |  |  |  * predicate and totalExpectedArgs values | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function addParam( | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |     params: o.Expression[], predicate: any, value: o.Expression | null, argNumber: number, | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |     totalExpectedArgs: number) { | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  |   if (predicate && value) { | 
					
						
							| 
									
										
										
										
											2018-12-13 15:51:47 -08:00
										 |  |  |     params.push(value); | 
					
						
							|  |  |  |   } else if (argNumber < totalExpectedArgs) { | 
					
						
							|  |  |  |     params.push(o.NULL_EXPR); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-02-08 15:03:54 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function parseProperty(name: string): | 
					
						
							|  |  |  |     {property: string, unit: string, hasOverrideFlag: boolean} { | 
					
						
							|  |  |  |   let hasOverrideFlag = false; | 
					
						
							|  |  |  |   const overrideIndex = name.indexOf(IMPORTANT_FLAG); | 
					
						
							|  |  |  |   if (overrideIndex !== -1) { | 
					
						
							|  |  |  |     name = overrideIndex > 0 ? name.substring(0, overrideIndex) : ''; | 
					
						
							|  |  |  |     hasOverrideFlag = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let unit = ''; | 
					
						
							|  |  |  |   let property = name; | 
					
						
							|  |  |  |   const unitIndex = name.lastIndexOf('.'); | 
					
						
							|  |  |  |   if (unitIndex > 0) { | 
					
						
							|  |  |  |     unit = name.substr(unitIndex + 1); | 
					
						
							|  |  |  |     property = name.substring(0, unitIndex); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return {property, unit, hasOverrideFlag}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-27 18:57:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Gets the instruction to generate for an interpolated class map. | 
					
						
							|  |  |  |  * @param interpolation An Interpolation AST | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function getClassMapInterpolationExpression(interpolation: Interpolation): o.ExternalReference { | 
					
						
							|  |  |  |   switch (getInterpolationArgsLength(interpolation)) { | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       return R3.classMap; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       return R3.classMapInterpolate1; | 
					
						
							|  |  |  |     case 5: | 
					
						
							|  |  |  |       return R3.classMapInterpolate2; | 
					
						
							|  |  |  |     case 7: | 
					
						
							|  |  |  |       return R3.classMapInterpolate3; | 
					
						
							|  |  |  |     case 9: | 
					
						
							|  |  |  |       return R3.classMapInterpolate4; | 
					
						
							|  |  |  |     case 11: | 
					
						
							|  |  |  |       return R3.classMapInterpolate5; | 
					
						
							|  |  |  |     case 13: | 
					
						
							|  |  |  |       return R3.classMapInterpolate6; | 
					
						
							|  |  |  |     case 15: | 
					
						
							|  |  |  |       return R3.classMapInterpolate7; | 
					
						
							|  |  |  |     case 17: | 
					
						
							|  |  |  |       return R3.classMapInterpolate8; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return R3.classMapInterpolateV; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Gets the instruction to generate for an interpolated style prop. | 
					
						
							|  |  |  |  * @param interpolation An Interpolation AST | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function getStylePropInterpolationExpression(interpolation: Interpolation) { | 
					
						
							|  |  |  |   switch (getInterpolationArgsLength(interpolation)) { | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       return R3.styleProp; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate1; | 
					
						
							|  |  |  |     case 5: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate2; | 
					
						
							|  |  |  |     case 7: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate3; | 
					
						
							|  |  |  |     case 9: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate4; | 
					
						
							|  |  |  |     case 11: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate5; | 
					
						
							|  |  |  |     case 13: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate6; | 
					
						
							|  |  |  |     case 15: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate7; | 
					
						
							|  |  |  |     case 17: | 
					
						
							|  |  |  |       return R3.stylePropInterpolate8; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return R3.stylePropInterpolateV; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-28 10:31:01 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | function normalizePropName(prop: string): string { | 
					
						
							|  |  |  |   return hyphenate(prop); | 
					
						
							|  |  |  | } |