From a9c3431a3ab37ef96150a7ab699718b30526f1a8 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Tue, 9 May 2017 20:36:49 +0300 Subject: [PATCH] fix(upgrade): fix transclusion on upgraded components Previously, only simple, single-slot transclusion worked on upgraded components. This commit fixes/adds support for the following: - Multi-slot transclusion. - Using fallback content when no transclusion content is provided. - Destroy unused scope (when using fallback content). This commit only affects `upgrade/static`. The dynamic version will be fixed in a follow-up PR. Fixes #13271 --- packages/upgrade/src/common/angular1.ts | 6 ++++-- packages/upgrade/src/common/util.ts | 8 ++++++++ packages/upgrade/test/common/test_helpers.ts | 5 +++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/upgrade/src/common/angular1.ts b/packages/upgrade/src/common/angular1.ts index 3e45a23cafdcd2..57bfeb9d40f234 100644 --- a/packages/upgrade/src/common/angular1.ts +++ b/packages/upgrade/src/common/angular1.ts @@ -33,6 +33,7 @@ export interface ICompileService { } export interface ILinkFn { (scope: IScope, cloneAttachFn?: ICloneAttachFunction, options?: ILinkFnOptions): IAugmentedJQuery; + $$slots?: {[slotName: string]: ILinkFn}; } export interface ILinkFnOptions { parentBoundTranscludeFn?: Function; @@ -75,9 +76,10 @@ export interface IDirective { templateUrl?: string|Function; templateNamespace?: string; terminal?: boolean; - transclude?: boolean|'element'|{[key: string]: string}; + transclude?: DirectiveTranscludeProperty; } export type DirectiveRequireProperty = SingleOrListOrMap; +export type DirectiveTranscludeProperty = boolean | 'element' | {[key: string]: string}; export interface IDirectiveCompileFn { (templateElement: IAugmentedJQuery, templateAttributes: IAttributes, transclude: ITranscludeFunction): IDirectivePrePost; @@ -97,7 +99,7 @@ export interface IComponent { require?: DirectiveRequireProperty; template?: string|Function; templateUrl?: string|Function; - transclude?: boolean; + transclude?: DirectiveTranscludeProperty; } export interface IAttributes { $observe(attr: string, fn: (v: string) => void): void; } export interface ITranscludeFunction { diff --git a/packages/upgrade/src/common/util.ts b/packages/upgrade/src/common/util.ts index cc1d1a086c2c33..22180802f11056 100644 --- a/packages/upgrade/src/common/util.ts +++ b/packages/upgrade/src/common/util.ts @@ -9,6 +9,9 @@ import {Type} from '@angular/core'; import * as angular from './angular1'; +const DIRECTIVE_PREFIX_REGEXP = /^(?:x|data)[:\-_]/i; +const DIRECTIVE_SPECIAL_CHARS_REGEXP = /[:\-_]+(.)/g; + export function onError(e: any) { // TODO: (misko): We seem to not have a stack trace here! if (console.error) { @@ -24,6 +27,11 @@ export function controllerKey(name: string): string { return '$' + name + 'Controller'; } +export function directiveNormalize(name: string): string { + return name.replace(DIRECTIVE_PREFIX_REGEXP, '') + .replace(DIRECTIVE_SPECIAL_CHARS_REGEXP, (_, letter) => letter.toUpperCase()); +} + export function getAttributesAsArray(node: Node): [string, string][] { const attributes = node.attributes; let asArray: [string, string][] = undefined !; diff --git a/packages/upgrade/test/common/test_helpers.ts b/packages/upgrade/test/common/test_helpers.ts index 037f59238c3299..827998ca76a470 100644 --- a/packages/upgrade/test/common/test_helpers.ts +++ b/packages/upgrade/test/common/test_helpers.ts @@ -20,9 +20,10 @@ export function html(html: string): Element { return div; } -export function multiTrim(text: string | null | undefined): string { +export function multiTrim(text: string | null | undefined, allSpace = false): string { if (typeof text == 'string') { - return text.replace(/\n/g, '').replace(/\s\s+/g, ' ').trim(); + const repl = allSpace ? '' : ' '; + return text.replace(/\n/g, '').replace(/\s+/g, repl).trim(); } throw new Error('Argument can not be undefined.'); }