angular/modules/@angular/upgrade/src/dynamic/content_projection_helper.ts
Georgios Kalpakas ea63676970 refactor(upgrade): use shared code in downgradeNg2Component() (#14037)
This unified the implementations of dynamic's `downgradeNg2Component()` and
static's `downgradeComponent()`.
2017-02-01 09:29:51 -06:00

70 lines
2.3 KiB
TypeScript

/**
* @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
*/
import {CssSelector, SelectorMatcher, createElementCssSelector} from '@angular/compiler';
import {Compiler, Type} from '@angular/core';
import * as angular from '../common/angular1';
import {COMPILER_KEY} from '../common/constants';
import {ContentProjectionHelper} from '../common/content_projection_helper';
import {getAttributesAsArray, getComponentName} from '../common/util';
export class DynamicContentProjectionHelper extends ContentProjectionHelper {
groupProjectableNodes($injector: angular.IInjectorService, component: Type<any>, nodes: Node[]):
Node[][] {
const ng2Compiler = $injector.get(COMPILER_KEY) as Compiler;
const ngContentSelectors = ng2Compiler.getNgContentSelectors(component);
if (!ngContentSelectors) {
throw new Error('Expecting ngContentSelectors for: ' + getComponentName(component));
}
return this.groupNodesBySelector(ngContentSelectors, nodes);
}
/**
* Group a set of DOM nodes into `ngContent` groups, based on the given content selectors.
*/
groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] {
const projectableNodes: Node[][] = [];
let matcher = new SelectorMatcher();
let wildcardNgContentIndex: number;
for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) {
projectableNodes[i] = [];
const selector = ngContentSelectors[i];
if (selector === '*') {
wildcardNgContentIndex = i;
} else {
matcher.addSelectables(CssSelector.parse(selector), i);
}
}
for (let j = 0, jj = nodes.length; j < jj; ++j) {
const ngContentIndices: number[] = [];
const node = nodes[j];
const selector =
createElementCssSelector(node.nodeName.toLowerCase(), getAttributesAsArray(node));
matcher.match(selector, (_, index) => ngContentIndices.push(index));
ngContentIndices.sort();
if (wildcardNgContentIndex !== undefined) {
ngContentIndices.push(wildcardNgContentIndex);
}
if (ngContentIndices.length) {
projectableNodes[ngContentIndices[0]].push(node);
}
}
return projectableNodes;
}
}