fix(compiler): support css stylesheets in offline compiler
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import * as selector from './src/selector';
|
||||
import * as pathUtil from './src/output/path_util';
|
||||
|
||||
export namespace __compiler_private__ {
|
||||
export type SelectorMatcher = selector.SelectorMatcher;
|
||||
@ -6,4 +7,10 @@ export namespace __compiler_private__ {
|
||||
|
||||
export type CssSelector = selector.CssSelector;
|
||||
export var CssSelector = selector.CssSelector;
|
||||
|
||||
export type AssetUrl = pathUtil.AssetUrl;
|
||||
export var AssetUrl = pathUtil.AssetUrl;
|
||||
|
||||
export type ImportGenerator = pathUtil.ImportGenerator;
|
||||
export var ImportGenerator = pathUtil.ImportGenerator;
|
||||
}
|
||||
|
@ -466,16 +466,13 @@ export class CompileTemplateMetadata {
|
||||
styles: string[];
|
||||
styleUrls: string[];
|
||||
ngContentSelectors: string[];
|
||||
baseUrl: string;
|
||||
constructor({encapsulation, template, templateUrl, styles, styleUrls, ngContentSelectors,
|
||||
baseUrl}: {
|
||||
constructor({encapsulation, template, templateUrl, styles, styleUrls, ngContentSelectors}: {
|
||||
encapsulation?: ViewEncapsulation,
|
||||
template?: string,
|
||||
templateUrl?: string,
|
||||
styles?: string[],
|
||||
styleUrls?: string[],
|
||||
ngContentSelectors?: string[],
|
||||
baseUrl?: string
|
||||
ngContentSelectors?: string[]
|
||||
} = {}) {
|
||||
this.encapsulation = isPresent(encapsulation) ? encapsulation : ViewEncapsulation.Emulated;
|
||||
this.template = template;
|
||||
@ -483,7 +480,6 @@ export class CompileTemplateMetadata {
|
||||
this.styles = isPresent(styles) ? styles : [];
|
||||
this.styleUrls = isPresent(styleUrls) ? styleUrls : [];
|
||||
this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : [];
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
|
||||
@ -495,8 +491,7 @@ export class CompileTemplateMetadata {
|
||||
templateUrl: data['templateUrl'],
|
||||
styles: data['styles'],
|
||||
styleUrls: data['styleUrls'],
|
||||
ngContentSelectors: data['ngContentSelectors'],
|
||||
baseUrl: data['baseUrl']
|
||||
ngContentSelectors: data['ngContentSelectors']
|
||||
});
|
||||
}
|
||||
|
||||
@ -508,8 +503,7 @@ export class CompileTemplateMetadata {
|
||||
'templateUrl': this.templateUrl,
|
||||
'styles': this.styles,
|
||||
'styleUrls': this.styleUrls,
|
||||
'ngContentSelectors': this.ngContentSelectors,
|
||||
'baseUrl': this.baseUrl
|
||||
'ngContentSelectors': this.ngContentSelectors
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -63,9 +63,9 @@ export class DirectiveNormalizer {
|
||||
template: CompileTemplateMetadata): Promise<CompileTemplateMetadata> {
|
||||
if (isPresent(template.template)) {
|
||||
return PromiseWrapper.resolve(this.normalizeLoadedTemplate(
|
||||
directiveType, template, template.template, template.baseUrl));
|
||||
directiveType, template, template.template, directiveType.moduleUrl));
|
||||
} else if (isPresent(template.templateUrl)) {
|
||||
var sourceAbsUrl = this._urlResolver.resolve(template.baseUrl, template.templateUrl);
|
||||
var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl);
|
||||
return this._xhr.get(sourceAbsUrl)
|
||||
.then(templateContent => this.normalizeLoadedTemplate(directiveType, template,
|
||||
templateContent, sourceAbsUrl));
|
||||
@ -90,7 +90,7 @@ export class DirectiveNormalizer {
|
||||
visitor.styleUrls.filter(isStyleUrlResolvable)
|
||||
.map(url => this._urlResolver.resolve(templateAbsUrl, url))
|
||||
.concat(templateMeta.styleUrls.filter(isStyleUrlResolvable)
|
||||
.map(url => this._urlResolver.resolve(templateMeta.baseUrl, url)));
|
||||
.map(url => this._urlResolver.resolve(directiveType.moduleUrl, url)));
|
||||
|
||||
var allResolvedStyles = allStyles.map(style => {
|
||||
var styleWithImports = extractStyleUrls(this._urlResolver, templateAbsUrl, style);
|
||||
|
@ -95,8 +95,7 @@ export class CompileMetadataResolver {
|
||||
template: viewMeta.template,
|
||||
templateUrl: viewMeta.templateUrl,
|
||||
styles: viewMeta.styles,
|
||||
styleUrls: viewMeta.styleUrls,
|
||||
baseUrl: calcTemplateBaseUrl(this._reflector, directiveType, cmpMeta)
|
||||
styleUrls: viewMeta.styleUrls
|
||||
});
|
||||
changeDetectionStrategy = cmpMeta.changeDetection;
|
||||
if (isPresent(dirMeta.viewProviders)) {
|
||||
@ -118,7 +117,10 @@ export class CompileMetadataResolver {
|
||||
selector: dirMeta.selector,
|
||||
exportAs: dirMeta.exportAs,
|
||||
isComponent: isPresent(templateMeta),
|
||||
type: this.getTypeMetadata(directiveType, staticTypeModuleUrl(directiveType)),
|
||||
type: this.getTypeMetadata(directiveType,
|
||||
isPresent(cmpMeta) ?
|
||||
componentModuleUrl(this._reflector, directiveType, cmpMeta) :
|
||||
staticTypeModuleUrl(dirMeta)),
|
||||
template: templateMeta,
|
||||
changeDetection: changeDetectionStrategy,
|
||||
inputs: dirMeta.inputs,
|
||||
@ -392,7 +394,7 @@ function flattenArray(tree: any[], out: Array<Type | any[]>): void {
|
||||
}
|
||||
|
||||
function isStaticType(value: any): boolean {
|
||||
return isStringMap(value) && isPresent(value['name']) && isPresent(value['moduleId']);
|
||||
return isStringMap(value) && isPresent(value['name']) && isPresent(value['filePath']);
|
||||
}
|
||||
|
||||
function isValidType(value: any): boolean {
|
||||
@ -400,13 +402,13 @@ function isValidType(value: any): boolean {
|
||||
}
|
||||
|
||||
function staticTypeModuleUrl(value: any): string {
|
||||
return isStaticType(value) ? value['moduleId'] : null;
|
||||
return isStaticType(value) ? value['filePath'] : null;
|
||||
}
|
||||
|
||||
function calcTemplateBaseUrl(reflector: ReflectorReader, type: any,
|
||||
cmpMetadata: ComponentMetadata): string {
|
||||
function componentModuleUrl(reflector: ReflectorReader, type: any,
|
||||
cmpMetadata: ComponentMetadata): string {
|
||||
if (isStaticType(type)) {
|
||||
return type['filePath'];
|
||||
return staticTypeModuleUrl(type);
|
||||
}
|
||||
|
||||
if (isPresent(cmpMetadata.moduleId)) {
|
||||
|
@ -15,6 +15,7 @@ import {TemplateParser} from './template_parser';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {OutputEmitter} from './output/abstract_emitter';
|
||||
import * as o from './output/output_ast';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
import {
|
||||
MODULE_SUFFIX,
|
||||
@ -31,6 +32,10 @@ export class SourceModule {
|
||||
constructor(public moduleUrl: string, public source: string) {}
|
||||
}
|
||||
|
||||
export class StyleSheetSourceWithImports {
|
||||
constructor(public source: SourceModule, public importedUrls: string[]) {}
|
||||
}
|
||||
|
||||
export class NormalizedComponentWithViewDirectives {
|
||||
constructor(public component: CompileDirectiveMetadata,
|
||||
public directives: CompileDirectiveMetadata[], public pipes: CompilePipeMetadata[]) {}
|
||||
@ -39,7 +44,8 @@ export class NormalizedComponentWithViewDirectives {
|
||||
export class OfflineCompiler {
|
||||
constructor(private _directiveNormalizer: DirectiveNormalizer,
|
||||
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
|
||||
private _viewCompiler: ViewCompiler, private _outputEmitter: OutputEmitter) {}
|
||||
private _viewCompiler: ViewCompiler, private _outputEmitter: OutputEmitter,
|
||||
private _xhr: XHR) {}
|
||||
|
||||
normalizeDirectiveMetadata(directive: CompileDirectiveMetadata):
|
||||
Promise<CompileDirectiveMetadata> {
|
||||
@ -80,15 +86,19 @@ export class OfflineCompiler {
|
||||
return this._codegenSourceModule(moduleUrl, statements, exportedVars);
|
||||
}
|
||||
|
||||
compileStylesheet(stylesheetUrl: string, cssText: string): SourceModule[] {
|
||||
var plainStyles = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, false);
|
||||
var shimStyles = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, true);
|
||||
return [
|
||||
this._codegenSourceModule(_stylesModuleUrl(stylesheetUrl, false),
|
||||
_resolveStyleStatements(plainStyles), [plainStyles.stylesVar]),
|
||||
this._codegenSourceModule(_stylesModuleUrl(stylesheetUrl, true),
|
||||
_resolveStyleStatements(shimStyles), [shimStyles.stylesVar])
|
||||
];
|
||||
loadAndCompileStylesheet(stylesheetUrl: string, shim: boolean,
|
||||
suffix: string): Promise<StyleSheetSourceWithImports> {
|
||||
return this._xhr.get(stylesheetUrl)
|
||||
.then((cssText) => {
|
||||
var compileResult = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, shim);
|
||||
var importedUrls = [];
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
importedUrls.push(dep.moduleUrl);
|
||||
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, suffix);
|
||||
});
|
||||
return new StyleSheetSourceWithImports(
|
||||
this._codgenStyles(stylesheetUrl, shim, suffix, compileResult), importedUrls);
|
||||
});
|
||||
}
|
||||
|
||||
private _compileComponent(compMeta: CompileDirectiveMetadata,
|
||||
@ -99,11 +109,18 @@ export class OfflineCompiler {
|
||||
directives, pipes, compMeta.type.name);
|
||||
var viewResult = this._viewCompiler.compileComponent(compMeta, parsedTemplate,
|
||||
o.variable(styleResult.stylesVar), pipes);
|
||||
ListWrapper.addAll(targetStatements, _resolveStyleStatements(styleResult));
|
||||
ListWrapper.addAll(targetStatements,
|
||||
_resolveStyleStatements(compMeta.type.moduleUrl, styleResult));
|
||||
ListWrapper.addAll(targetStatements, _resolveViewStatements(viewResult));
|
||||
return viewResult.viewFactoryVar;
|
||||
}
|
||||
|
||||
private _codgenStyles(inputUrl: string, shim: boolean, suffix: string,
|
||||
stylesCompileResult: StylesCompileResult): SourceModule {
|
||||
return this._codegenSourceModule(_stylesModuleUrl(inputUrl, shim, suffix),
|
||||
stylesCompileResult.statements,
|
||||
[stylesCompileResult.stylesVar]);
|
||||
}
|
||||
|
||||
private _codegenSourceModule(moduleUrl: string, statements: o.Statement[],
|
||||
exportedVars: string[]): SourceModule {
|
||||
@ -119,21 +136,23 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
|
||||
}
|
||||
|
||||
|
||||
function _resolveStyleStatements(compileResult: StylesCompileResult): o.Statement[] {
|
||||
function _resolveStyleStatements(containingModuleUrl: string,
|
||||
compileResult: StylesCompileResult): o.Statement[] {
|
||||
var containingSuffix = _splitSuffix(containingModuleUrl)[1];
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.sourceUrl, dep.isShimmed);
|
||||
dep.valuePlaceholder.moduleUrl =
|
||||
_stylesModuleUrl(dep.moduleUrl, dep.isShimmed, containingSuffix);
|
||||
});
|
||||
return compileResult.statements;
|
||||
}
|
||||
|
||||
function _templateModuleUrl(comp: CompileDirectiveMetadata): string {
|
||||
var moduleUrl = comp.type.moduleUrl;
|
||||
var urlWithoutSuffix = moduleUrl.substring(0, moduleUrl.length - MODULE_SUFFIX.length);
|
||||
return `${urlWithoutSuffix}.ngfactory${MODULE_SUFFIX}`;
|
||||
var urlWithSuffix = _splitSuffix(comp.type.moduleUrl);
|
||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||
}
|
||||
|
||||
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean): string {
|
||||
return shim ? `${stylesheetUrl}.shim${MODULE_SUFFIX}` : `${stylesheetUrl}${MODULE_SUFFIX}`;
|
||||
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
|
||||
return shim ? `${stylesheetUrl}.shim${suffix}` : `${stylesheetUrl}${suffix}`;
|
||||
}
|
||||
|
||||
function _assertComponent(meta: CompileDirectiveMetadata) {
|
||||
@ -141,3 +160,12 @@ function _assertComponent(meta: CompileDirectiveMetadata) {
|
||||
throw new BaseException(`Could not compile '${meta.type.name}' because it is not a component.`);
|
||||
}
|
||||
}
|
||||
|
||||
function _splitSuffix(path: string): string[] {
|
||||
let lastDot = path.lastIndexOf('.');
|
||||
if (lastDot !== -1) {
|
||||
return [path.substring(0, lastDot), path.substring(lastDot)];
|
||||
} else {
|
||||
return [path, ''];
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import {
|
||||
CATCH_ERROR_VAR,
|
||||
CATCH_STACK_VAR,
|
||||
} from './abstract_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
import {ImportGenerator} from './path_util';
|
||||
|
||||
var _debugModuleUrl = 'asset://debug/lib';
|
||||
|
||||
@ -37,7 +37,7 @@ export function debugOutputAstAsDart(ast: o.Statement | o.Expression | o.Type |
|
||||
}
|
||||
|
||||
export class DartEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
constructor(private _importGenerator: ImportGenerator) {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var srcParts = [];
|
||||
// Note: We are not creating a library here as Dart does not need it.
|
||||
@ -49,7 +49,7 @@ export class DartEmitter implements OutputEmitter {
|
||||
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
|
||||
srcParts.push(
|
||||
`import '${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.Dart)}' as ${prefix};`);
|
||||
`import '${this._importGenerator.getImportPath(moduleUrl, importedModuleUrl)}' as ${prefix};`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
|
52
modules/@angular/compiler/src/output/dart_imports.ts
Normal file
52
modules/@angular/compiler/src/output/dart_imports.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import {BaseException} from '../../src/facade/exceptions';
|
||||
import {isPresent, isBlank, RegExpWrapper, Math} from '../../src/facade/lang';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
import {AssetUrl, ImportGenerator} from './path_util';
|
||||
|
||||
var _PATH_SEP = '/';
|
||||
var _PATH_SEP_RE = /\//g;
|
||||
|
||||
@Injectable()
|
||||
export class DartImportGenerator implements ImportGenerator {
|
||||
getImportPath(moduleUrlStr: string, importedUrlStr: string): string {
|
||||
var moduleUrl = AssetUrl.parse(moduleUrlStr, false);
|
||||
var importedUrl = AssetUrl.parse(importedUrlStr, true);
|
||||
if (isBlank(importedUrl)) {
|
||||
return importedUrlStr;
|
||||
}
|
||||
// Try to create a relative path first
|
||||
if (moduleUrl.firstLevelDir == importedUrl.firstLevelDir &&
|
||||
moduleUrl.packageName == importedUrl.packageName) {
|
||||
return getRelativePath(moduleUrl.modulePath, importedUrl.modulePath);
|
||||
} else if (importedUrl.firstLevelDir == 'lib') {
|
||||
return `package:${importedUrl.packageName}/${importedUrl.modulePath}`;
|
||||
}
|
||||
throw new BaseException(`Can't import url ${importedUrlStr} from ${moduleUrlStr}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function getRelativePath(modulePath: string, importedPath: string): string {
|
||||
var moduleParts = modulePath.split(_PATH_SEP_RE);
|
||||
var importedParts = importedPath.split(_PATH_SEP_RE);
|
||||
var longestPrefix = getLongestPathSegmentPrefix(moduleParts, importedParts);
|
||||
|
||||
var resultParts = [];
|
||||
var goParentCount = moduleParts.length - 1 - longestPrefix;
|
||||
for (var i = 0; i < goParentCount; i++) {
|
||||
resultParts.push('..');
|
||||
}
|
||||
for (var i = longestPrefix; i < importedParts.length; i++) {
|
||||
resultParts.push(importedParts[i]);
|
||||
}
|
||||
return resultParts.join(_PATH_SEP);
|
||||
}
|
||||
|
||||
export function getLongestPathSegmentPrefix(arr1: string[], arr2: string[]): number {
|
||||
var prefixSize = 0;
|
||||
var minLen = Math.min(arr1.length, arr2.length);
|
||||
while (prefixSize < minLen && arr1[prefixSize] == arr2[prefixSize]) {
|
||||
prefixSize++;
|
||||
}
|
||||
return prefixSize;
|
||||
}
|
@ -10,10 +10,10 @@ import {
|
||||
import {BaseException} from '@angular/core';
|
||||
import {OutputEmitter, EmitterVisitorContext} from './abstract_emitter';
|
||||
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
import {ImportGenerator} from './path_util';
|
||||
|
||||
export class JavaScriptEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
constructor(private _importGenerator: ImportGenerator) {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var converter = new JsEmitterVisitor(moduleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
@ -21,8 +21,9 @@ export class JavaScriptEmitter implements OutputEmitter {
|
||||
var srcParts = [];
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
srcParts.push(`var ${prefix} = req` +
|
||||
`uire('${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.JS)}');`);
|
||||
srcParts.push(
|
||||
`var ${prefix} = req` +
|
||||
`uire('${this._importGenerator.getImportPath(moduleUrl, importedModuleUrl)}');`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
|
@ -1,44 +1,24 @@
|
||||
import {BaseException} from '../../src/facade/exceptions';
|
||||
import {isPresent, isBlank, RegExpWrapper, Math} from '../../src/facade/lang';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
// asset:<package-name>/<realm>/<path-to-module>
|
||||
var _ASSET_URL_RE = /asset:([^\/]+)\/([^\/]+)\/(.+)/g;
|
||||
|
||||
var _PATH_SEP = '/';
|
||||
var _PATH_SEP_RE = /\//g;
|
||||
|
||||
export enum ImportEnv {
|
||||
Dart,
|
||||
JS
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module path to use for an import.
|
||||
* Interface that defines how import statements should be generated.
|
||||
*/
|
||||
export function getImportModulePath(moduleUrlStr: string, importedUrlStr: string,
|
||||
importEnv: ImportEnv): string {
|
||||
var absolutePathPrefix: string = importEnv === ImportEnv.Dart ? `package:` : '';
|
||||
var moduleUrl = _AssetUrl.parse(moduleUrlStr, false);
|
||||
var importedUrl = _AssetUrl.parse(importedUrlStr, true);
|
||||
if (isBlank(importedUrl)) {
|
||||
return importedUrlStr;
|
||||
}
|
||||
export abstract class ImportGenerator {
|
||||
static parseAssetUrl(url: string): AssetUrl { return AssetUrl.parse(url); }
|
||||
|
||||
// Try to create a relative path first
|
||||
if (moduleUrl.firstLevelDir == importedUrl.firstLevelDir &&
|
||||
moduleUrl.packageName == importedUrl.packageName) {
|
||||
return getRelativePath(moduleUrl.modulePath, importedUrl.modulePath, importEnv);
|
||||
} else if (importedUrl.firstLevelDir == 'lib') {
|
||||
return `${absolutePathPrefix}${importedUrl.packageName}/${importedUrl.modulePath}`;
|
||||
}
|
||||
throw new BaseException(`Can't import url ${importedUrlStr} from ${moduleUrlStr}`);
|
||||
abstract getImportPath(moduleUrlStr: string, importedUrlStr: string): string;
|
||||
}
|
||||
|
||||
class _AssetUrl {
|
||||
static parse(url: string, allowNonMatching: boolean): _AssetUrl {
|
||||
export class AssetUrl {
|
||||
static parse(url: string, allowNonMatching: boolean = true): AssetUrl {
|
||||
var match = RegExpWrapper.firstMatch(_ASSET_URL_RE, url);
|
||||
if (isPresent(match)) {
|
||||
return new _AssetUrl(match[1], match[2], match[3]);
|
||||
return new AssetUrl(match[1], match[2], match[3]);
|
||||
}
|
||||
if (allowNonMatching) {
|
||||
return null;
|
||||
@ -49,32 +29,3 @@ class _AssetUrl {
|
||||
constructor(public packageName: string, public firstLevelDir: string, public modulePath: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getRelativePath(modulePath: string, importedPath: string,
|
||||
importEnv: ImportEnv): string {
|
||||
var moduleParts = modulePath.split(_PATH_SEP_RE);
|
||||
var importedParts = importedPath.split(_PATH_SEP_RE);
|
||||
var longestPrefix = getLongestPathSegmentPrefix(moduleParts, importedParts);
|
||||
|
||||
var resultParts = [];
|
||||
var goParentCount = moduleParts.length - 1 - longestPrefix;
|
||||
for (var i = 0; i < goParentCount; i++) {
|
||||
resultParts.push('..');
|
||||
}
|
||||
if (goParentCount <= 0 && importEnv === ImportEnv.JS) {
|
||||
resultParts.push('.');
|
||||
}
|
||||
for (var i = longestPrefix; i < importedParts.length; i++) {
|
||||
resultParts.push(importedParts[i]);
|
||||
}
|
||||
return resultParts.join(_PATH_SEP);
|
||||
}
|
||||
|
||||
export function getLongestPathSegmentPrefix(arr1: string[], arr2: string[]): number {
|
||||
var prefixSize = 0;
|
||||
var minLen = Math.min(arr1.length, arr2.length);
|
||||
while (prefixSize < minLen && arr1[prefixSize] == arr2[prefixSize]) {
|
||||
prefixSize++;
|
||||
}
|
||||
return prefixSize;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
CATCH_ERROR_VAR,
|
||||
CATCH_STACK_VAR
|
||||
} from './abstract_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
import {ImportGenerator} from './path_util';
|
||||
|
||||
var _debugModuleUrl = 'asset://debug/lib';
|
||||
|
||||
@ -38,7 +38,7 @@ export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.T
|
||||
}
|
||||
|
||||
export class TypeScriptEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
constructor(private _importGenerator: ImportGenerator) {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var converter = new _TsEmitterVisitor(moduleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
@ -48,7 +48,7 @@ export class TypeScriptEmitter implements OutputEmitter {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
srcParts.push(
|
||||
`imp` +
|
||||
`ort * as ${prefix} from '${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.JS)}';`);
|
||||
`ort * as ${prefix} from '${this._importGenerator.getImportPath(moduleUrl, importedModuleUrl)}';`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
|
@ -160,9 +160,9 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
var dep = result.dependencies[i];
|
||||
var cssText = cssTexts[i];
|
||||
var nestedCompileResult =
|
||||
this._styleCompiler.compileStylesheet(dep.sourceUrl, cssText, dep.isShimmed);
|
||||
this._styleCompiler.compileStylesheet(dep.moduleUrl, cssText, dep.isShimmed);
|
||||
nestedCompileResultPromises.push(
|
||||
this._resolveStylesCompileResult(dep.sourceUrl, nestedCompileResult));
|
||||
this._resolveStylesCompileResult(dep.moduleUrl, nestedCompileResult));
|
||||
}
|
||||
return PromiseWrapper.all(nestedCompileResultPromises);
|
||||
})
|
||||
@ -182,10 +182,10 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
}
|
||||
|
||||
private _loadStylesheetDep(dep: StylesCompileDependency): Promise<string> {
|
||||
var cacheKey = `${dep.sourceUrl}${dep.isShimmed ? '.shim' : ''}`;
|
||||
var cacheKey = `${dep.moduleUrl}${dep.isShimmed ? '.shim' : ''}`;
|
||||
var cssTextPromise = this._styleCache.get(cacheKey);
|
||||
if (isBlank(cssTextPromise)) {
|
||||
cssTextPromise = this._xhr.get(dep.sourceUrl);
|
||||
cssTextPromise = this._xhr.get(dep.moduleUrl);
|
||||
this._styleCache.set(cacheKey, cssTextPromise);
|
||||
}
|
||||
return cssTextPromise;
|
||||
|
@ -11,7 +11,7 @@ const HOST_ATTR = /*@ts2dart_const*/ `_nghost-${COMPONENT_VARIABLE}`;
|
||||
const CONTENT_ATTR = /*@ts2dart_const*/ `_ngcontent-${COMPONENT_VARIABLE}`;
|
||||
|
||||
export class StylesCompileDependency {
|
||||
constructor(public sourceUrl: string, public isShimmed: boolean,
|
||||
constructor(public moduleUrl: string, public isShimmed: boolean,
|
||||
public valuePlaceholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,7 @@ export function main() {
|
||||
templateUrl: 'someTemplateUrl',
|
||||
styles: ['someStyle'],
|
||||
styleUrls: ['someStyleUrl'],
|
||||
ngContentSelectors: ['*'],
|
||||
baseUrl: 'someBaseUrl'
|
||||
ngContentSelectors: ['*']
|
||||
});
|
||||
fullDirectiveMeta = CompileDirectiveMetadata.create({
|
||||
selector: 'someSelector',
|
||||
|
@ -21,10 +21,15 @@ import {TEST_PROVIDERS} from './test_bindings';
|
||||
export function main() {
|
||||
describe('DirectiveNormalizer', () => {
|
||||
var dirType: CompileTypeMetadata;
|
||||
var dirTypeWithHttpUrl: CompileTypeMetadata;
|
||||
|
||||
beforeEachProviders(() => TEST_PROVIDERS);
|
||||
|
||||
beforeEach(() => { dirType = new CompileTypeMetadata({name: 'SomeComp'}); });
|
||||
beforeEach(() => {
|
||||
dirType = new CompileTypeMetadata({moduleUrl: 'package:some/module/a.js', name: 'SomeComp'});
|
||||
dirTypeWithHttpUrl =
|
||||
new CompileTypeMetadata({moduleUrl: 'http://some/module/a.js', name: 'SomeComp'});
|
||||
});
|
||||
|
||||
describe('loadTemplate', () => {
|
||||
describe('inline template', () => {
|
||||
@ -36,8 +41,7 @@ export function main() {
|
||||
template: 'a',
|
||||
templateUrl: null,
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: ['test.css']
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.template).toEqual('a');
|
||||
@ -46,7 +50,7 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should resolve styles on the annotation against the baseUrl',
|
||||
it('should resolve styles on the annotation against the moduleUrl',
|
||||
inject([AsyncTestCompleter, DirectiveNormalizer],
|
||||
(async, normalizer: DirectiveNormalizer) => {
|
||||
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
|
||||
@ -54,8 +58,7 @@ export function main() {
|
||||
template: '',
|
||||
templateUrl: null,
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: ['test.css']
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
|
||||
@ -63,7 +66,7 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should resolve styles in the template against the baseUrl',
|
||||
it('should resolve styles in the template against the moduleUrl',
|
||||
inject([AsyncTestCompleter, DirectiveNormalizer],
|
||||
(async, normalizer: DirectiveNormalizer) => {
|
||||
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
|
||||
@ -71,8 +74,7 @@ export function main() {
|
||||
template: '<style>@import test.css</style>',
|
||||
templateUrl: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: []
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
|
||||
@ -83,7 +85,7 @@ export function main() {
|
||||
|
||||
describe('templateUrl', () => {
|
||||
|
||||
it('should load a template from a url that is resolved against baseUrl',
|
||||
it('should load a template from a url that is resolved against moduleUrl',
|
||||
inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
|
||||
(async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
|
||||
xhr.expect('package:some/module/sometplurl.html', 'a');
|
||||
@ -92,8 +94,7 @@ export function main() {
|
||||
template: null,
|
||||
templateUrl: 'sometplurl.html',
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: ['test.css']
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.template).toEqual('a');
|
||||
@ -104,7 +105,7 @@ export function main() {
|
||||
xhr.flush();
|
||||
}));
|
||||
|
||||
it('should resolve styles on the annotation against the baseUrl',
|
||||
it('should resolve styles on the annotation against the moduleUrl',
|
||||
inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
|
||||
(async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
|
||||
xhr.expect('package:some/module/tpl/sometplurl.html', '');
|
||||
@ -113,8 +114,7 @@ export function main() {
|
||||
template: null,
|
||||
templateUrl: 'tpl/sometplurl.html',
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: ['test.css']
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
|
||||
@ -133,8 +133,7 @@ export function main() {
|
||||
template: null,
|
||||
templateUrl: 'tpl/sometplurl.html',
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: []
|
||||
}))
|
||||
.then((template: CompileTemplateMetadata) => {
|
||||
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
|
||||
@ -160,50 +159,36 @@ export function main() {
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
|
||||
var viewEncapsulation = ViewEncapsulation.Native;
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: viewEncapsulation,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'', 'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata(
|
||||
{encapsulation: viewEncapsulation, styles: [], styleUrls: []}),
|
||||
'', 'package:some/module/');
|
||||
expect(template.encapsulation).toBe(viewEncapsulation);
|
||||
}));
|
||||
|
||||
it('should keep the template as html',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'a', 'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}), 'a',
|
||||
'package:some/module/');
|
||||
expect(template.template).toEqual('a')
|
||||
}));
|
||||
|
||||
it('should collect ngContent',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'<ng-content select="a"></ng-content>',
|
||||
'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<ng-content select="a"></ng-content>', 'package:some/module/');
|
||||
expect(template.ngContentSelectors).toEqual(['a']);
|
||||
}));
|
||||
|
||||
it('should normalize ngContent wildcard selector',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<ng-content></ng-content><ng-content select></ng-content><ng-content select="*"></ng-content>',
|
||||
'package:some/module/');
|
||||
expect(template.ngContentSelectors).toEqual(['*', '*', '*']);
|
||||
@ -211,91 +196,64 @@ export function main() {
|
||||
|
||||
it('should collect top level styles in the template',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template =
|
||||
normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'<style>a</style>', 'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<style>a</style>', 'package:some/module/');
|
||||
expect(template.styles).toEqual(['a']);
|
||||
}));
|
||||
|
||||
it('should collect styles inside in elements',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'<div><style>a</style></div>',
|
||||
'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<div><style>a</style></div>', 'package:some/module/');
|
||||
expect(template.styles).toEqual(['a']);
|
||||
}));
|
||||
|
||||
it('should collect styleUrls in the template',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'<link rel="stylesheet" href="aUrl">',
|
||||
'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<link rel="stylesheet" href="aUrl">', 'package:some/module/');
|
||||
expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
|
||||
}));
|
||||
|
||||
it('should collect styleUrls in elements',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<div><link rel="stylesheet" href="aUrl"></div>', 'package:some/module/');
|
||||
expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
|
||||
}));
|
||||
|
||||
it('should ignore link elements with non stylesheet rel attribute',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'<link href="b" rel="a">',
|
||||
'package:some/module/');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<link href="b" rel="a">', 'package:some/module/');
|
||||
expect(template.styleUrls).toEqual([]);
|
||||
}));
|
||||
|
||||
it('should ignore link elements with absolute urls but non package: scheme',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<link href="http://some/external.css" rel="stylesheet">', 'package:some/module/');
|
||||
expect(template.styleUrls).toEqual([]);
|
||||
}));
|
||||
|
||||
it('should extract @import style urls into styleAbsUrl',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: ['@import "test.css";'],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'', 'package:some/module/id');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata(
|
||||
{encapsulation: null, styles: ['@import "test.css";'], styleUrls: []}),
|
||||
'', 'package:some/module/id');
|
||||
expect(template.styles).toEqual(['']);
|
||||
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
|
||||
}));
|
||||
@ -306,8 +264,7 @@ export function main() {
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: ['.foo{background-image: url(\'double.jpg\');'],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
styleUrls: []
|
||||
}),
|
||||
'', 'package:some/module/id');
|
||||
expect(template.styles).toEqual(['.foo{background-image: url(\'double.jpg\');']);
|
||||
@ -315,52 +272,38 @@ export function main() {
|
||||
|
||||
it('should resolve relative style urls in styleUrls',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'', 'package:some/module/id');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata(
|
||||
{encapsulation: null, styles: [], styleUrls: ['test.css']}),
|
||||
'', 'package:some/module/id');
|
||||
expect(template.styles).toEqual([]);
|
||||
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
|
||||
}));
|
||||
|
||||
it('should resolve relative style urls in styleUrls with http directive url',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: ['test.css'],
|
||||
baseUrl: 'http://some/module/a.js'
|
||||
}),
|
||||
'', 'http://some/module/id');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirTypeWithHttpUrl, new CompileTemplateMetadata(
|
||||
{encapsulation: null, styles: [], styleUrls: ['test.css']}),
|
||||
'', 'http://some/module/id');
|
||||
expect(template.styles).toEqual([]);
|
||||
expect(template.styleUrls).toEqual(['http://some/module/test.css']);
|
||||
}));
|
||||
|
||||
it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template =
|
||||
normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
|
||||
encapsulation: ViewEncapsulation.Emulated,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
'', 'package:some/module/id');
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata(
|
||||
{encapsulation: ViewEncapsulation.Emulated, styles: [], styleUrls: []}),
|
||||
'', 'package:some/module/id');
|
||||
expect(template.encapsulation).toEqual(ViewEncapsulation.None);
|
||||
}));
|
||||
|
||||
it('should ignore ng-content in elements with ngNonBindable',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<div ngNonBindable><ng-content select="a"></ng-content></div>',
|
||||
'package:some/module/');
|
||||
expect(template.ngContentSelectors).toEqual([]);
|
||||
@ -369,12 +312,8 @@ export function main() {
|
||||
it('should still collect <style> in elements with ngNonBindable',
|
||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||
var template = normalizer.normalizeLoadedTemplate(
|
||||
dirType, new CompileTemplateMetadata({
|
||||
encapsulation: null,
|
||||
styles: [],
|
||||
styleUrls: [],
|
||||
baseUrl: 'package:some/module/a.js'
|
||||
}),
|
||||
dirType,
|
||||
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
|
||||
'<div ngNonBindable><style>div {color:red}</style></div>', 'package:some/module/');
|
||||
expect(template.styles).toEqual(['div {color:red}']);
|
||||
}));
|
||||
|
@ -62,13 +62,12 @@ export function main() {
|
||||
expect(meta.template.styleUrls).toEqual(['someStyleUrl']);
|
||||
expect(meta.template.template).toEqual('someTemplate');
|
||||
expect(meta.template.templateUrl).toEqual('someTemplateUrl');
|
||||
expect(meta.template.baseUrl).toEqual(`package:someModuleId${MODULE_SUFFIX}`);
|
||||
}));
|
||||
|
||||
it('should use the moduleUrl from the reflector if none is given',
|
||||
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
||||
var value: string =
|
||||
resolver.getDirectiveMetadata(ComponentWithoutModuleId).template.baseUrl;
|
||||
resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl;
|
||||
var expectedEndValue =
|
||||
IS_DART ? 'test/compiler/metadata_resolver_spec.dart' : './ComponentWithoutModuleId';
|
||||
expect(value.endsWith(expectedEndValue)).toBe(true);
|
||||
|
@ -2,15 +2,17 @@
|
||||
import {print, IS_DART} from '../src/facade/lang';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {DartEmitter} from '@angular/compiler/src/output/dart_emitter';
|
||||
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {compileComp, compAMetadata} from './offline_compiler_util';
|
||||
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
|
||||
import {CompA} from './offline_compiler_util';
|
||||
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
|
||||
|
||||
export const CompANgFactory: ComponentFactory<CompA> = null;
|
||||
|
||||
export function emit(): Promise<string> {
|
||||
var emitter = IS_DART ? new DartEmitter() : new TypeScriptEmitter();
|
||||
var emitter = IS_DART ? new DartEmitter(new DartImportGenerator()) :
|
||||
new TypeScriptEmitter(new SimpleJsImportGenerator());
|
||||
return compileComp(emitter, compAMetadata);
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,12 @@ import {print} from '../src/facade/lang';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {compileComp, compAMetadata} from './offline_compiler_util';
|
||||
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
|
||||
import {CompA} from './offline_compiler_util';
|
||||
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
|
||||
|
||||
export const CompANgFactory: ComponentFactory<CompA> = null;
|
||||
|
||||
export function emit() {
|
||||
var emitter = new JavaScriptEmitter();
|
||||
var emitter = new JavaScriptEmitter(new SimpleJsImportGenerator());
|
||||
return compileComp(emitter, compAMetadata);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {print, IS_DART} from '../src/facade/lang';
|
||||
import {print, isPresent, IS_DART} from '../src/facade/lang';
|
||||
import {OutputEmitter} from '@angular/compiler/src/output/abstract_emitter';
|
||||
import {Console} from '../core_private';
|
||||
|
||||
@ -19,6 +19,7 @@ import {createOfflineCompileUrlResolver} from '@angular/compiler/src/url_resolve
|
||||
import {MockSchemaRegistry} from '../testing/schema_registry_mock';
|
||||
import {MODULE_SUFFIX} from '@angular/compiler/src/util';
|
||||
import {MockXHR} from '../testing/xhr_mock';
|
||||
import {ImportGenerator} from '@angular/compiler/src/output/path_util';
|
||||
|
||||
import {
|
||||
CompileDirectiveMetadata,
|
||||
@ -29,7 +30,7 @@ import {
|
||||
|
||||
export class CompA { user: string; }
|
||||
|
||||
var THIS_MODULE_PATH = `asset:angular2/test/compiler`;
|
||||
var THIS_MODULE_PATH = `asset:@angular/lib/compiler/test`;
|
||||
var THIS_MODULE_URL = `${THIS_MODULE_PATH}/offline_compiler_util${MODULE_SUFFIX}`;
|
||||
|
||||
export var compAMetadata = CompileDirectiveMetadata.create({
|
||||
@ -40,8 +41,7 @@ export var compAMetadata = CompileDirectiveMetadata.create({
|
||||
template: new CompileTemplateMetadata({
|
||||
templateUrl: './offline_compiler_compa.html',
|
||||
styles: ['.redStyle { color: red; }'],
|
||||
styleUrls: ['./offline_compiler_compa.css'],
|
||||
baseUrl: THIS_MODULE_URL,
|
||||
styleUrls: ['./offline_compiler_compa.css']
|
||||
})
|
||||
});
|
||||
|
||||
@ -54,7 +54,7 @@ function _createOfflineCompiler(xhr: MockXHR, emitter: OutputEmitter): OfflineCo
|
||||
normalizer, new TemplateParser(new Parser(new Lexer()), new MockSchemaRegistry({}, {}),
|
||||
htmlParser, new Console(), []),
|
||||
new StyleCompiler(urlResolver), new ViewCompiler(new CompilerConfig(true, true, true)),
|
||||
emitter);
|
||||
emitter, xhr);
|
||||
}
|
||||
|
||||
export function compileComp(emitter: OutputEmitter,
|
||||
@ -68,3 +68,15 @@ export function compileComp(emitter: OutputEmitter,
|
||||
xhr.flush();
|
||||
return result;
|
||||
}
|
||||
|
||||
export class SimpleJsImportGenerator implements ImportGenerator {
|
||||
getImportPath(moduleUrlStr: string, importedUrlStr: string): string {
|
||||
// var moduleAssetUrl = ImportGenerator.parseAssetUrl(moduleUrlStr);
|
||||
var importedAssetUrl = ImportGenerator.parseAssetUrl(importedUrlStr);
|
||||
if (isPresent(importedAssetUrl)) {
|
||||
return `${importedAssetUrl.packageName}/${importedAssetUrl.modulePath}`;
|
||||
} else {
|
||||
return importedUrlStr;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import {isBlank} from '../../src/facade/lang';
|
||||
import {DartEmitter} from '@angular/compiler/src/output/dart_emitter';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
|
||||
|
||||
var someModuleUrl = 'asset:somePackage/lib/somePath';
|
||||
var anotherModuleUrl = 'asset:somePackage/lib/someOtherPath';
|
||||
@ -36,7 +37,7 @@ export function main() {
|
||||
var someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
emitter = new DartEmitter();
|
||||
emitter = new DartEmitter(new DartImportGenerator());
|
||||
someVar = o.variable('someVar');
|
||||
});
|
||||
|
||||
|
64
modules/@angular/compiler/test/output/dart_imports_spec.ts
Normal file
64
modules/@angular/compiler/test/output/dart_imports_spec.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import {
|
||||
beforeEach,
|
||||
ddescribe,
|
||||
describe,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
it,
|
||||
xit,
|
||||
} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
|
||||
|
||||
export function main() {
|
||||
describe('DartImportGenerator', () => {
|
||||
describe('getImportPath', () => {
|
||||
var generator: DartImportGenerator;
|
||||
beforeEach(() => { generator = new DartImportGenerator(); });
|
||||
|
||||
it('should calculate relative paths Dart', () => {
|
||||
expect(generator.getImportPath('asset:somePkg/lib/modPath', 'asset:somePkg/lib/impPath'))
|
||||
.toEqual('impPath');
|
||||
});
|
||||
|
||||
it('should calculate relative paths for different constellations', () => {
|
||||
expect(generator.getImportPath('asset:somePkg/test/modPath', 'asset:somePkg/test/impPath'))
|
||||
.toEqual('impPath');
|
||||
expect(
|
||||
generator.getImportPath('asset:somePkg/lib/modPath', 'asset:somePkg/lib/dir2/impPath'))
|
||||
.toEqual('dir2/impPath');
|
||||
expect(
|
||||
generator.getImportPath('asset:somePkg/lib/dir1/modPath', 'asset:somePkg/lib/impPath'))
|
||||
.toEqual('../impPath');
|
||||
expect(generator.getImportPath('asset:somePkg/lib/dir1/modPath',
|
||||
'asset:somePkg/lib/dir2/impPath'))
|
||||
.toEqual('../dir2/impPath');
|
||||
});
|
||||
|
||||
it('should calculate absolute paths', () => {
|
||||
expect(
|
||||
generator.getImportPath('asset:somePkg/lib/modPath', 'asset:someOtherPkg/lib/impPath'))
|
||||
.toEqual('package:someOtherPkg/impPath');
|
||||
});
|
||||
|
||||
it('should not allow absolute imports of non lib modules', () => {
|
||||
expect(() => generator.getImportPath('asset:somePkg/lib/modPath',
|
||||
'asset:somePkg/test/impPath'))
|
||||
.toThrowError(
|
||||
`Can't import url asset:somePkg/test/impPath from asset:somePkg/lib/modPath`);
|
||||
});
|
||||
|
||||
it('should not allow non asset urls as base url', () => {
|
||||
expect(
|
||||
() => generator.getImportPath('http:somePkg/lib/modPath', 'asset:somePkg/test/impPath'))
|
||||
.toThrowError(`Url http:somePkg/lib/modPath is not a valid asset: url`);
|
||||
});
|
||||
|
||||
it('should allow non asset urls as import urls and pass them through', () => {
|
||||
expect(generator.getImportPath('asset:somePkg/lib/modPath', 'dart:html'))
|
||||
.toEqual('dart:html');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -13,6 +13,7 @@ import {isBlank} from '../../src/facade/lang';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
var someModuleUrl = 'asset:somePackage/lib/somePath';
|
||||
var anotherModuleUrl = 'asset:somePackage/lib/someOtherPath';
|
||||
@ -33,7 +34,7 @@ export function main() {
|
||||
var someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
emitter = new JavaScriptEmitter();
|
||||
emitter = new JavaScriptEmitter(new SimpleJsImportGenerator());
|
||||
someVar = o.variable('someVar');
|
||||
});
|
||||
|
||||
@ -111,9 +112,10 @@ export function main() {
|
||||
it('should support external identifiers', () => {
|
||||
expect(emitStmt(o.importExpr(sameModuleIdentifier).toStmt())).toEqual('someLocalId;');
|
||||
expect(emitStmt(o.importExpr(externalModuleIdentifier).toStmt()))
|
||||
.toEqual(
|
||||
[`var import0 = re` + `quire('./someOtherPath');`, `import0.someExternalId;`].join(
|
||||
'\n'));
|
||||
.toEqual([
|
||||
`var import0 = re` + `quire('somePackage/someOtherPath');`,
|
||||
`import0.someExternalId;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support operators', () => {
|
||||
|
@ -4,8 +4,10 @@ import {unimplemented} from '../../src/facade/exceptions';
|
||||
import {codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {DartEmitter} from '@angular/compiler/src/output/dart_emitter';
|
||||
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {assetUrl} from '../../src/util';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
export function getExpressions(): any {
|
||||
return unimplemented();
|
||||
@ -13,7 +15,8 @@ export function getExpressions(): any {
|
||||
|
||||
// Generator
|
||||
export function emit() {
|
||||
var emitter = IS_DART ? new DartEmitter() : new TypeScriptEmitter();
|
||||
var emitter = IS_DART ? new DartEmitter(new DartImportGenerator()) :
|
||||
new TypeScriptEmitter(new SimpleJsImportGenerator());
|
||||
var emittedCode =
|
||||
emitter.emitStatements(assetUrl('compiler', 'output/output_emitter_codegen_typed', 'test'),
|
||||
codegenStmts, codegenExportsVars);
|
||||
|
@ -4,6 +4,7 @@ import {unimplemented} from '../../src/facade/exceptions';
|
||||
import {codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {assetUrl} from '../../src/util';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
export function getExpressions(): any {
|
||||
return unimplemented();
|
||||
@ -11,7 +12,7 @@ export function getExpressions(): any {
|
||||
|
||||
// Generator
|
||||
export function emit() {
|
||||
var emitter = new JavaScriptEmitter();
|
||||
var emitter = new JavaScriptEmitter(new SimpleJsImportGenerator());
|
||||
var emittedCode =
|
||||
emitter.emitStatements(assetUrl('compiler', 'output/output_emitter_codegen_untyped', 'test'),
|
||||
codegenStmts, codegenExportsVars);
|
||||
|
@ -15,7 +15,7 @@ export class ExternalClass {
|
||||
|
||||
var testDataIdentifier = new CompileIdentifierMetadata({
|
||||
name: 'ExternalClass',
|
||||
moduleUrl: assetUrl('compiler', 'output/output_emitter_util'),
|
||||
moduleUrl: `asset:@angular/lib/compiler/test/output/output_emitter_util`,
|
||||
runtime: ExternalClass
|
||||
});
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
import {
|
||||
beforeEach,
|
||||
ddescribe,
|
||||
describe,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
it,
|
||||
xit,
|
||||
} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {getImportModulePath, ImportEnv} from '@angular/compiler/src/output/path_util';
|
||||
|
||||
export function main() {
|
||||
describe('PathUtils', () => {
|
||||
describe('getImportModulePath', () => {
|
||||
it('should calculate relative paths for JS and Dart', () => {
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'asset:somePkg/lib/impPath',
|
||||
ImportEnv.JS))
|
||||
.toEqual('./impPath');
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'asset:somePkg/lib/impPath',
|
||||
ImportEnv.Dart))
|
||||
.toEqual('impPath');
|
||||
});
|
||||
|
||||
it('should calculate relative paths for different constellations', () => {
|
||||
expect(getImportModulePath('asset:somePkg/test/modPath', 'asset:somePkg/test/impPath',
|
||||
ImportEnv.JS))
|
||||
.toEqual('./impPath');
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'asset:somePkg/lib/dir2/impPath',
|
||||
ImportEnv.JS))
|
||||
.toEqual('./dir2/impPath');
|
||||
expect(getImportModulePath('asset:somePkg/lib/dir1/modPath', 'asset:somePkg/lib/impPath',
|
||||
ImportEnv.JS))
|
||||
.toEqual('../impPath');
|
||||
expect(getImportModulePath('asset:somePkg/lib/dir1/modPath',
|
||||
'asset:somePkg/lib/dir2/impPath', ImportEnv.JS))
|
||||
.toEqual('../dir2/impPath');
|
||||
});
|
||||
|
||||
it('should calculate absolute paths for JS and Dart', () => {
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'asset:someOtherPkg/lib/impPath',
|
||||
ImportEnv.JS))
|
||||
.toEqual('someOtherPkg/impPath');
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'asset:someOtherPkg/lib/impPath',
|
||||
ImportEnv.Dart))
|
||||
.toEqual('package:someOtherPkg/impPath');
|
||||
});
|
||||
|
||||
it('should not allow absolute imports of non lib modules', () => {
|
||||
expect(() => getImportModulePath('asset:somePkg/lib/modPath', 'asset:somePkg/test/impPath',
|
||||
ImportEnv.Dart))
|
||||
.toThrowError(
|
||||
`Can't import url asset:somePkg/test/impPath from asset:somePkg/lib/modPath`);
|
||||
});
|
||||
|
||||
it('should not allow non asset urls as base url', () => {
|
||||
expect(() => getImportModulePath('http:somePkg/lib/modPath', 'asset:somePkg/test/impPath',
|
||||
ImportEnv.Dart))
|
||||
.toThrowError(`Url http:somePkg/lib/modPath is not a valid asset: url`);
|
||||
});
|
||||
|
||||
it('should allow non asset urls as import urls and pass them through', () => {
|
||||
expect(getImportModulePath('asset:somePkg/lib/modPath', 'dart:html', ImportEnv.Dart))
|
||||
.toEqual('dart:html');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -13,6 +13,7 @@ import {isBlank} from '../../src/facade/lang';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
var someModuleUrl = 'asset:somePackage/lib/somePath';
|
||||
var anotherModuleUrl = 'asset:somePackage/lib/someOtherPath';
|
||||
@ -33,7 +34,7 @@ export function main() {
|
||||
var someVar: o.ReadVarExpr;
|
||||
|
||||
beforeEach(() => {
|
||||
emitter = new TypeScriptEmitter();
|
||||
emitter = new TypeScriptEmitter(new SimpleJsImportGenerator());
|
||||
someVar = o.variable('someVar');
|
||||
});
|
||||
|
||||
@ -112,8 +113,10 @@ export function main() {
|
||||
it('should support external identifiers', () => {
|
||||
expect(emitStmt(o.importExpr(sameModuleIdentifier).toStmt())).toEqual('someLocalId;');
|
||||
expect(emitStmt(o.importExpr(externalModuleIdentifier).toStmt()))
|
||||
.toEqual([`import * as import0 from './someOtherPath';`, `import0.someExternalId;`].join(
|
||||
'\n'));
|
||||
.toEqual([
|
||||
`import * as import0 from 'somePackage/someOtherPath';`,
|
||||
`import0.someExternalId;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should support operators', () => {
|
||||
@ -302,7 +305,7 @@ export function main() {
|
||||
.toEqual('var a:someLocalId = null;');
|
||||
expect(emitStmt(writeVarExpr.toDeclStmt(o.importType(externalModuleIdentifier))))
|
||||
.toEqual([
|
||||
`import * as import0 from './someOtherPath';`,
|
||||
`import * as import0 from 'somePackage/someOtherPath';`,
|
||||
`var a:import0.someExternalId = null;`
|
||||
].join('\n'));
|
||||
});
|
||||
|
Reference in New Issue
Block a user