refactor(ivy): flatten css selectors (#23074)

PR Close #23074
This commit is contained in:
Kara Erickson
2018-03-29 16:41:45 -07:00
committed by Alex Rickabaugh
parent 6cb1adf105
commit 6e5fb99304
44 changed files with 631 additions and 361 deletions

View File

@ -12,7 +12,7 @@ import {Provider} from '../../core';
import {RendererType2} from '../../render/api';
import {Type} from '../../type';
import {resolveRendererType2} from '../../view/util';
import {CssSelector} from './projection';
import {CssSelectorList} from './projection';
/**
@ -61,8 +61,8 @@ export interface DirectiveDef<T> {
/** Function that makes a directive public to the DI system. */
diPublic: ((def: DirectiveDef<any>) => void)|null;
/** The selector that will be used to match nodes to this directive. */
selector: CssSelector;
/** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList;
/**
* A dictionary mapping the inputs' minified property names to their public API names, which

View File

@ -17,33 +17,61 @@ export interface LProjection {
}
/**
* Parsed selector in the following format:
* [tagName, attr1Name, attr1Val, ..., attrnName, attrnValue, 'class', className1, className2, ...,
* classNameN]
* Expresses a single CSS Selector.
*
* * For example, given the following selector:
* `div.foo.bar[attr1=val1][attr2]` a parsed format would be:
* `['div', 'attr1', 'val1', 'attr2', '', 'class', 'foo', 'bar']`.
* Beginning of array
* - First index: element name
* - Subsequent odd indices: attr keys
* - Subsequent even indices: attr values
*
* Things to notice:
* - tag name is always at the position 0
* - the `class` attribute is always the last attribute in a pre-parsed array
* - class names in a selector are at the end of an array (after the attribute with the name
* 'class').
* After SelectorFlags.CLASS flag
* - Class name values
*
* SelectorFlags.NOT flag
* - Changes the mode to NOT
* - Can be combined with other flags to set the element / attr / class mode
*
* e.g. SelectorFlags.NOT | SelectorFlags.ELEMENT
*
* Example:
* Original: `div.foo.bar[attr1=val1][attr2]`
* Parsed: ['div', 'attr1', 'val1', 'attr2', '', SelectorFlags.CLASS, 'foo', 'bar']
*
* Original: 'div[attr1]:not(.foo[attr2])
* Parsed: [
* 'div', 'attr1', '',
* SelectorFlags.NOT | SelectorFlags.ATTRIBUTE 'attr2', '', SelectorFlags.CLASS, 'foo'
* ]
*
* See more examples in node_selector_matcher_spec.ts
*/
export type SimpleCssSelector = string[];
export type CssSelector = (string | SelectorFlags)[];
/**
* A complex selector expressed as an Array where:
* - element at index 0 is a selector (SimpleCSSSelector) to match
* - elements at index 1..n is a selector (SimpleCSSSelector) that should NOT match
* A list of CssSelectors.
*
* A directive or component can have multiple selectors. This type is used for
* directive defs so any of the selectors in the list will match that directive.
*
* Original: 'form, [ngForm]'
* Parsed: [['form'], ['', 'ngForm', '']]
*/
export type CssSelectorWithNegations = [SimpleCssSelector | null, SimpleCssSelector[] | null];
export type CssSelectorList = CssSelector[];
/**
* A collection of complex selectors (CSSSelectorWithNegations) in a parsed form
*/
export type CssSelector = CssSelectorWithNegations[];
/** Flags used to build up CssSelectors */
export const enum SelectorFlags {
/** Indicates this is the beginning of a new negative selector */
NOT = 0b0001,
/** Mode for matching attributes */
ATTRIBUTE = 0b0010,
/** Mode for matching tag names */
ELEMENT = 0b0100,
/** Mode for matching class names */
CLASS = 0b1000,
}
export const NG_PROJECT_AS_ATTR_NAME = 'ngProjectAs';