2015-09-18 10:33:23 -07:00
|
|
|
import {
|
|
|
|
isPresent,
|
|
|
|
isBlank,
|
|
|
|
normalizeBool,
|
|
|
|
serializeEnum,
|
|
|
|
Type,
|
|
|
|
RegExpWrapper,
|
|
|
|
StringWrapper
|
2015-11-06 17:34:07 -08:00
|
|
|
} from 'angular2/src/facade/lang';
|
2015-12-02 10:35:51 -08:00
|
|
|
import {unimplemented} from 'angular2/src/facade/exceptions';
|
2015-11-06 17:34:07 -08:00
|
|
|
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
2015-09-11 13:35:46 -07:00
|
|
|
import {
|
|
|
|
ChangeDetectionStrategy,
|
2015-10-11 22:30:47 -07:00
|
|
|
CHANGE_DETECTION_STRATEGY_VALUES
|
2015-09-11 13:35:46 -07:00
|
|
|
} from 'angular2/src/core/change_detection/change_detection';
|
2015-10-05 10:10:07 -07:00
|
|
|
import {ViewEncapsulation, VIEW_ENCAPSULATION_VALUES} from 'angular2/src/core/metadata/view';
|
2015-11-05 14:07:57 -08:00
|
|
|
import {CssSelector} from 'angular2/src/compiler/selector';
|
2015-09-18 10:33:23 -07:00
|
|
|
import {splitAtColon} from './util';
|
2015-10-02 07:37:23 -07:00
|
|
|
import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/interfaces';
|
2015-09-18 10:33:23 -07:00
|
|
|
|
|
|
|
// group 1: "property" from "[property]"
|
|
|
|
// group 2: "event" from "(event)"
|
|
|
|
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
2015-08-25 15:36:02 -07:00
|
|
|
|
2016-02-08 12:14:45 -08:00
|
|
|
export abstract class CompileMetadataWithType {
|
2015-12-02 10:35:51 -08:00
|
|
|
static fromJson(data: {[key: string]: any}): CompileMetadataWithType {
|
|
|
|
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract toJson(): {[key: string]: any};
|
|
|
|
|
|
|
|
get type(): CompileTypeMetadata { return unimplemented(); }
|
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Metadata regarding compilation of a type.
|
|
|
|
*/
|
2016-02-08 12:14:45 -08:00
|
|
|
export class CompileTypeMetadata {
|
2015-09-14 15:59:09 -07:00
|
|
|
runtime: Type;
|
|
|
|
name: string;
|
2015-10-01 10:07:49 -07:00
|
|
|
moduleUrl: string;
|
|
|
|
isHost: boolean;
|
2016-02-08 12:14:45 -08:00
|
|
|
constructor({runtime, name, moduleUrl, isHost}:
|
|
|
|
{runtime?: Type, name?: string, moduleUrl?: string, isHost?: boolean} = {}) {
|
2015-09-14 15:59:09 -07:00
|
|
|
this.runtime = runtime;
|
|
|
|
this.name = name;
|
2015-10-01 10:07:49 -07:00
|
|
|
this.moduleUrl = moduleUrl;
|
|
|
|
this.isHost = normalizeBool(isHost);
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
2015-09-11 13:35:46 -07:00
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
2016-02-08 12:14:45 -08:00
|
|
|
return new CompileTypeMetadata(
|
|
|
|
{name: data['name'], moduleUrl: data['moduleUrl'], isHost: data['isHost']});
|
2015-09-11 13:35:46 -07:00
|
|
|
}
|
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
toJson(): {[key: string]: any} {
|
2015-09-11 13:35:46 -07:00
|
|
|
return {
|
|
|
|
// Note: Runtime type can't be serialized...
|
2015-09-14 15:59:09 -07:00
|
|
|
'name': this.name,
|
2015-10-01 10:07:49 -07:00
|
|
|
'moduleUrl': this.moduleUrl,
|
2016-02-08 12:14:45 -08:00
|
|
|
'isHost': this.isHost
|
2015-09-11 13:35:46 -07:00
|
|
|
};
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Metadata regarding compilation of a template.
|
|
|
|
*/
|
2015-09-18 10:33:23 -07:00
|
|
|
export class CompileTemplateMetadata {
|
2015-09-14 15:59:09 -07:00
|
|
|
encapsulation: ViewEncapsulation;
|
|
|
|
template: string;
|
|
|
|
templateUrl: string;
|
|
|
|
styles: string[];
|
|
|
|
styleUrls: string[];
|
2015-09-18 10:33:23 -07:00
|
|
|
ngContentSelectors: string[];
|
|
|
|
constructor({encapsulation, template, templateUrl, styles, styleUrls, ngContentSelectors}: {
|
2015-09-14 15:59:09 -07:00
|
|
|
encapsulation?: ViewEncapsulation,
|
|
|
|
template?: string,
|
|
|
|
templateUrl?: string,
|
|
|
|
styles?: string[],
|
|
|
|
styleUrls?: string[],
|
2015-09-18 10:33:23 -07:00
|
|
|
ngContentSelectors?: string[]
|
2015-09-14 15:59:09 -07:00
|
|
|
} = {}) {
|
2015-10-05 09:49:05 -07:00
|
|
|
this.encapsulation = isPresent(encapsulation) ? encapsulation : ViewEncapsulation.Emulated;
|
2015-09-14 15:59:09 -07:00
|
|
|
this.template = template;
|
|
|
|
this.templateUrl = templateUrl;
|
|
|
|
this.styles = isPresent(styles) ? styles : [];
|
|
|
|
this.styleUrls = isPresent(styleUrls) ? styleUrls : [];
|
2015-09-18 10:33:23 -07:00
|
|
|
this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : [];
|
2015-09-14 15:59:09 -07:00
|
|
|
}
|
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
|
2015-09-18 10:33:23 -07:00
|
|
|
return new CompileTemplateMetadata({
|
2015-09-11 13:35:46 -07:00
|
|
|
encapsulation: isPresent(data['encapsulation']) ?
|
2015-09-18 10:33:23 -07:00
|
|
|
VIEW_ENCAPSULATION_VALUES[data['encapsulation']] :
|
2015-09-11 13:35:46 -07:00
|
|
|
data['encapsulation'],
|
|
|
|
template: data['template'],
|
2015-09-18 10:33:23 -07:00
|
|
|
templateUrl: data['templateUrl'],
|
2015-09-11 13:35:46 -07:00
|
|
|
styles: data['styles'],
|
2015-09-18 10:33:23 -07:00
|
|
|
styleUrls: data['styleUrls'],
|
|
|
|
ngContentSelectors: data['ngContentSelectors']
|
2015-09-11 13:35:46 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
toJson(): {[key: string]: any} {
|
2015-09-11 13:35:46 -07:00
|
|
|
return {
|
|
|
|
'encapsulation':
|
|
|
|
isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) : this.encapsulation,
|
|
|
|
'template': this.template,
|
2015-09-18 10:33:23 -07:00
|
|
|
'templateUrl': this.templateUrl,
|
2015-09-11 13:35:46 -07:00
|
|
|
'styles': this.styles,
|
2015-09-18 10:33:23 -07:00
|
|
|
'styleUrls': this.styleUrls,
|
|
|
|
'ngContentSelectors': this.ngContentSelectors
|
2015-09-11 13:35:46 -07:00
|
|
|
};
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Metadata regarding compilation of a directive.
|
|
|
|
*/
|
2015-12-02 10:35:51 -08:00
|
|
|
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
2015-09-30 20:59:23 -07:00
|
|
|
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
2016-02-08 12:14:45 -08:00
|
|
|
outputs, host, lifecycleHooks, template}: {
|
2015-09-18 10:33:23 -07:00
|
|
|
type?: CompileTypeMetadata,
|
|
|
|
isComponent?: boolean,
|
|
|
|
dynamicLoadable?: boolean,
|
|
|
|
selector?: string,
|
|
|
|
exportAs?: string,
|
|
|
|
changeDetection?: ChangeDetectionStrategy,
|
2015-09-30 20:59:23 -07:00
|
|
|
inputs?: string[],
|
|
|
|
outputs?: string[],
|
2015-10-02 16:47:54 -07:00
|
|
|
host?: {[key: string]: string},
|
2015-09-18 10:33:23 -07:00
|
|
|
lifecycleHooks?: LifecycleHooks[],
|
|
|
|
template?: CompileTemplateMetadata
|
|
|
|
} = {}): CompileDirectiveMetadata {
|
2015-10-02 17:33:21 -07:00
|
|
|
var hostListeners: {[key: string]: string} = {};
|
|
|
|
var hostProperties: {[key: string]: string} = {};
|
|
|
|
var hostAttributes: {[key: string]: string} = {};
|
2015-09-18 10:33:23 -07:00
|
|
|
if (isPresent(host)) {
|
|
|
|
StringMapWrapper.forEach(host, (value: string, key: string) => {
|
|
|
|
var matches = RegExpWrapper.firstMatch(HOST_REG_EXP, key);
|
|
|
|
if (isBlank(matches)) {
|
|
|
|
hostAttributes[key] = value;
|
|
|
|
} else if (isPresent(matches[1])) {
|
|
|
|
hostProperties[matches[1]] = value;
|
|
|
|
} else if (isPresent(matches[2])) {
|
|
|
|
hostListeners[matches[2]] = value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-10-02 17:33:21 -07:00
|
|
|
var inputsMap: {[key: string]: string} = {};
|
2015-09-30 20:59:23 -07:00
|
|
|
if (isPresent(inputs)) {
|
|
|
|
inputs.forEach((bindConfig: string) => {
|
2015-09-18 10:33:23 -07:00
|
|
|
// canonical syntax: `dirProp: elProp`
|
|
|
|
// if there is no `:`, use dirProp = elProp
|
|
|
|
var parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
|
2015-09-30 20:59:23 -07:00
|
|
|
inputsMap[parts[0]] = parts[1];
|
2015-09-18 10:33:23 -07:00
|
|
|
});
|
|
|
|
}
|
2015-10-02 17:33:21 -07:00
|
|
|
var outputsMap: {[key: string]: string} = {};
|
2015-09-30 20:59:23 -07:00
|
|
|
if (isPresent(outputs)) {
|
|
|
|
outputs.forEach((bindConfig: string) => {
|
2015-09-18 10:33:23 -07:00
|
|
|
// canonical syntax: `dirProp: elProp`
|
|
|
|
// if there is no `:`, use dirProp = elProp
|
|
|
|
var parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
|
2015-09-30 20:59:23 -07:00
|
|
|
outputsMap[parts[0]] = parts[1];
|
2015-09-18 10:33:23 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return new CompileDirectiveMetadata({
|
|
|
|
type: type,
|
|
|
|
isComponent: normalizeBool(isComponent),
|
|
|
|
dynamicLoadable: normalizeBool(dynamicLoadable),
|
|
|
|
selector: selector,
|
|
|
|
exportAs: exportAs,
|
|
|
|
changeDetection: changeDetection,
|
2015-09-30 20:59:23 -07:00
|
|
|
inputs: inputsMap,
|
|
|
|
outputs: outputsMap,
|
2015-09-18 10:33:23 -07:00
|
|
|
hostListeners: hostListeners,
|
|
|
|
hostProperties: hostProperties,
|
|
|
|
hostAttributes: hostAttributes,
|
2015-10-28 08:59:19 +01:00
|
|
|
lifecycleHooks: isPresent(lifecycleHooks) ? lifecycleHooks : [],
|
|
|
|
template: template
|
2015-09-18 10:33:23 -07:00
|
|
|
});
|
|
|
|
}
|
2016-02-08 12:14:45 -08:00
|
|
|
|
2015-09-18 10:33:23 -07:00
|
|
|
type: CompileTypeMetadata;
|
2015-08-27 09:03:18 -07:00
|
|
|
isComponent: boolean;
|
2015-09-14 15:59:09 -07:00
|
|
|
dynamicLoadable: boolean;
|
2015-08-25 15:36:02 -07:00
|
|
|
selector: string;
|
2015-09-18 10:33:23 -07:00
|
|
|
exportAs: string;
|
|
|
|
changeDetection: ChangeDetectionStrategy;
|
2015-10-02 16:47:54 -07:00
|
|
|
inputs: {[key: string]: string};
|
|
|
|
outputs: {[key: string]: string};
|
|
|
|
hostListeners: {[key: string]: string};
|
|
|
|
hostProperties: {[key: string]: string};
|
|
|
|
hostAttributes: {[key: string]: string};
|
2015-09-18 10:33:23 -07:00
|
|
|
lifecycleHooks: LifecycleHooks[];
|
|
|
|
template: CompileTemplateMetadata;
|
2015-09-30 20:59:23 -07:00
|
|
|
constructor({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
2016-02-08 12:14:45 -08:00
|
|
|
outputs, hostListeners, hostProperties, hostAttributes, lifecycleHooks, template}: {
|
2015-09-18 10:33:23 -07:00
|
|
|
type?: CompileTypeMetadata,
|
2015-08-27 09:03:18 -07:00
|
|
|
isComponent?: boolean,
|
2015-09-14 15:59:09 -07:00
|
|
|
dynamicLoadable?: boolean,
|
2015-08-27 09:03:18 -07:00
|
|
|
selector?: string,
|
2015-09-18 10:33:23 -07:00
|
|
|
exportAs?: string,
|
|
|
|
changeDetection?: ChangeDetectionStrategy,
|
2015-10-02 16:47:54 -07:00
|
|
|
inputs?: {[key: string]: string},
|
|
|
|
outputs?: {[key: string]: string},
|
|
|
|
hostListeners?: {[key: string]: string},
|
|
|
|
hostProperties?: {[key: string]: string},
|
|
|
|
hostAttributes?: {[key: string]: string},
|
2015-09-18 10:33:23 -07:00
|
|
|
lifecycleHooks?: LifecycleHooks[],
|
|
|
|
template?: CompileTemplateMetadata
|
2015-08-27 09:03:18 -07:00
|
|
|
} = {}) {
|
2015-08-25 15:36:02 -07:00
|
|
|
this.type = type;
|
2015-09-18 10:33:23 -07:00
|
|
|
this.isComponent = isComponent;
|
|
|
|
this.dynamicLoadable = dynamicLoadable;
|
2015-08-25 15:36:02 -07:00
|
|
|
this.selector = selector;
|
2015-09-18 10:33:23 -07:00
|
|
|
this.exportAs = exportAs;
|
2015-08-27 16:29:02 -07:00
|
|
|
this.changeDetection = changeDetection;
|
2015-09-30 20:59:23 -07:00
|
|
|
this.inputs = inputs;
|
|
|
|
this.outputs = outputs;
|
2015-09-18 10:33:23 -07:00
|
|
|
this.hostListeners = hostListeners;
|
|
|
|
this.hostProperties = hostProperties;
|
|
|
|
this.hostAttributes = hostAttributes;
|
|
|
|
this.lifecycleHooks = lifecycleHooks;
|
2015-08-25 15:36:02 -07:00
|
|
|
this.template = template;
|
|
|
|
}
|
2015-09-11 13:35:46 -07:00
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
|
2015-09-18 10:33:23 -07:00
|
|
|
return new CompileDirectiveMetadata({
|
2015-09-11 13:35:46 -07:00
|
|
|
isComponent: data['isComponent'],
|
2015-09-14 15:59:09 -07:00
|
|
|
dynamicLoadable: data['dynamicLoadable'],
|
2015-09-11 13:35:46 -07:00
|
|
|
selector: data['selector'],
|
2015-09-18 10:33:23 -07:00
|
|
|
exportAs: data['exportAs'],
|
|
|
|
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
|
2015-09-11 13:35:46 -07:00
|
|
|
changeDetection: isPresent(data['changeDetection']) ?
|
2015-10-11 22:30:47 -07:00
|
|
|
CHANGE_DETECTION_STRATEGY_VALUES[data['changeDetection']] :
|
2015-09-11 13:35:46 -07:00
|
|
|
data['changeDetection'],
|
2015-09-30 20:59:23 -07:00
|
|
|
inputs: data['inputs'],
|
|
|
|
outputs: data['outputs'],
|
2015-09-18 10:33:23 -07:00
|
|
|
hostListeners: data['hostListeners'],
|
|
|
|
hostProperties: data['hostProperties'],
|
|
|
|
hostAttributes: data['hostAttributes'],
|
|
|
|
lifecycleHooks:
|
|
|
|
(<any[]>data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
|
|
|
|
template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
|
2016-02-08 12:14:45 -08:00
|
|
|
data['template']
|
2015-09-11 13:35:46 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-10-02 16:47:54 -07:00
|
|
|
toJson(): {[key: string]: any} {
|
2015-09-11 13:35:46 -07:00
|
|
|
return {
|
2015-12-02 10:35:51 -08:00
|
|
|
'class': 'Directive',
|
2015-09-11 13:35:46 -07:00
|
|
|
'isComponent': this.isComponent,
|
2015-09-14 15:59:09 -07:00
|
|
|
'dynamicLoadable': this.dynamicLoadable,
|
2015-09-11 13:35:46 -07:00
|
|
|
'selector': this.selector,
|
2015-09-18 10:33:23 -07:00
|
|
|
'exportAs': this.exportAs,
|
2015-09-14 15:59:09 -07:00
|
|
|
'type': isPresent(this.type) ? this.type.toJson() : this.type,
|
2015-09-18 10:33:23 -07:00
|
|
|
'changeDetection': isPresent(this.changeDetection) ? serializeEnum(this.changeDetection) :
|
|
|
|
this.changeDetection,
|
2015-09-30 20:59:23 -07:00
|
|
|
'inputs': this.inputs,
|
|
|
|
'outputs': this.outputs,
|
2015-09-18 10:33:23 -07:00
|
|
|
'hostListeners': this.hostListeners,
|
|
|
|
'hostProperties': this.hostProperties,
|
|
|
|
'hostAttributes': this.hostAttributes,
|
|
|
|
'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
|
2016-02-08 12:14:45 -08:00
|
|
|
'template': isPresent(this.template) ? this.template.toJson() : this.template
|
2015-09-11 13:35:46 -07:00
|
|
|
};
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
2015-09-02 15:07:31 -07:00
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
|
|
|
|
*/
|
2015-09-18 10:33:23 -07:00
|
|
|
export function createHostComponentMeta(componentType: CompileTypeMetadata,
|
|
|
|
componentSelector: string): CompileDirectiveMetadata {
|
2015-09-14 15:59:09 -07:00
|
|
|
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
|
2015-09-18 10:33:23 -07:00
|
|
|
return CompileDirectiveMetadata.create({
|
2015-10-01 10:07:49 -07:00
|
|
|
type: new CompileTypeMetadata({
|
|
|
|
runtime: Object,
|
|
|
|
name: `Host${componentType.name}`,
|
|
|
|
moduleUrl: componentType.moduleUrl,
|
|
|
|
isHost: true
|
|
|
|
}),
|
2015-09-18 10:33:23 -07:00
|
|
|
template: new CompileTemplateMetadata(
|
|
|
|
{template: template, templateUrl: '', styles: [], styleUrls: [], ngContentSelectors: []}),
|
|
|
|
changeDetection: ChangeDetectionStrategy.Default,
|
2015-09-30 20:59:23 -07:00
|
|
|
inputs: [],
|
|
|
|
outputs: [],
|
2015-09-18 10:33:23 -07:00
|
|
|
host: {},
|
|
|
|
lifecycleHooks: [],
|
2015-09-14 15:59:09 -07:00
|
|
|
isComponent: true,
|
|
|
|
dynamicLoadable: false,
|
2016-02-08 12:14:45 -08:00
|
|
|
selector: '*'
|
2015-09-14 15:59:09 -07:00
|
|
|
});
|
2015-09-02 15:07:31 -07:00
|
|
|
}
|
2015-12-02 10:35:51 -08:00
|
|
|
|
|
|
|
|
|
|
|
export class CompilePipeMetadata implements CompileMetadataWithType {
|
|
|
|
type: CompileTypeMetadata;
|
|
|
|
name: string;
|
|
|
|
pure: boolean;
|
|
|
|
constructor({type, name,
|
|
|
|
pure}: {type?: CompileTypeMetadata, name?: string, pure?: boolean} = {}) {
|
|
|
|
this.type = type;
|
|
|
|
this.name = name;
|
|
|
|
this.pure = normalizeBool(pure);
|
|
|
|
}
|
|
|
|
|
|
|
|
static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
|
|
|
|
return new CompilePipeMetadata({
|
|
|
|
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
|
|
|
|
name: data['name'],
|
|
|
|
pure: data['pure']
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
toJson(): {[key: string]: any} {
|
|
|
|
return {
|
|
|
|
'class': 'Pipe',
|
|
|
|
'type': isPresent(this.type) ? this.type.toJson() : null,
|
|
|
|
'name': this.name,
|
|
|
|
'pure': this.pure
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var _COMPILE_METADATA_FROM_JSON = {
|
|
|
|
'Directive': CompileDirectiveMetadata.fromJson,
|
2016-02-08 12:14:45 -08:00
|
|
|
'Pipe': CompilePipeMetadata.fromJson
|
2015-12-02 10:35:51 -08:00
|
|
|
};
|