@@ -3,8 +3,13 @@ import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
33import * as ts from 'typescript' ;
44import { addModuleImportToRootModule , getSourceFile } from '../utils/ast' ;
55import { createCustomTheme } from '../utils/custom-theme' ;
6- import { addSymbolToNgModuleMetadata , findNodes , insertAfterLastOccurrence } from '../utils/devkit-utils/ast-utils' ;
7- import { InsertChange } from '../utils/devkit-utils/change' ;
6+ import {
7+ addSymbolToNgModuleMetadata ,
8+ findNodes ,
9+ getDecoratorMetadata ,
10+ insertAfterLastOccurrence
11+ } from '../utils/devkit-utils/ast-utils' ;
12+ import { Change , InsertChange , ReplaceChange } from '../utils/devkit-utils/change' ;
813import { getProjectFromWorkspace , getWorkspace , Project , Workspace } from '../utils/devkit-utils/config' ;
914import { getAppModulePath } from '../utils/devkit-utils/ng-ast-utils' ;
1015import { insertImport } from '../utils/devkit-utils/route-utils' ;
@@ -42,29 +47,96 @@ function addI18n(options: Schema): (host: Tree) => Tree {
4247 throw new SchematicsException ( `Invalid locale-symbol` ) ;
4348 }
4449
45- const allImports = findNodes ( moduleSource , ts . SyntaxKind . ImportDeclaration ) ;
46-
4750 const changes = [
4851 insertImport ( moduleSource , modulePath , 'NZ_I18N' , 'ng-zorro-antd' ) ,
4952 insertImport ( moduleSource , modulePath , locale , 'ng-zorro-antd' ) ,
5053 insertImport ( moduleSource , modulePath , 'registerLocaleData' , '@angular/common' ) ,
5154 insertImport ( moduleSource , modulePath , localePrefix , `@angular/common/locales/${ localePrefix } ` , true ) ,
52- ... addSymbolToNgModuleMetadata ( moduleSource , modulePath , 'providers' , `{ provide: NZ_I18N, useValue: ${ locale } }` , null ) ,
53- insertAfterLastOccurrence ( allImports , `\n\nregisterLocaleData( ${ localePrefix } );` , modulePath , 0 )
55+ registerLocaleData ( moduleSource , modulePath , localePrefix ) ,
56+ ... insertI18nTokenProvide ( moduleSource , modulePath , locale )
5457 ] ;
5558
5659 const recorder = host . beginUpdate ( modulePath ) ;
5760 changes . forEach ( ( change ) => {
5861 if ( change instanceof InsertChange ) {
5962 recorder . insertLeft ( change . pos , change . toAdd ) ;
6063 }
64+
65+ if ( change instanceof ReplaceChange ) {
66+ recorder . remove ( change . pos , change . oldText . length ) ;
67+ recorder . insertLeft ( change . pos , change . newText ) ;
68+ }
69+
6170 } ) ;
6271
6372 host . commitUpdate ( recorder ) ;
6473 return host ;
6574 } ;
6675}
6776
77+ function insertI18nTokenProvide ( moduleSource : ts . SourceFile , modulePath : string , locale : string ) : Change [ ] {
78+ const metadataField = 'providers' ;
79+ const nodes = getDecoratorMetadata ( moduleSource , 'NgModule' , '@angular/core' ) ;
80+ const addProvide = addSymbolToNgModuleMetadata ( moduleSource , modulePath , 'providers' , `{ provide: NZ_I18N, useValue: ${ locale } }` , null ) ;
81+ let node : any = nodes [ 0 ] ; // tslint:disable-line:no-any
82+
83+ if ( ! node ) {
84+ return [ ] ;
85+ }
86+
87+ const matchingProperties : ts . ObjectLiteralElement [ ] =
88+ ( node as ts . ObjectLiteralExpression ) . properties
89+ . filter ( prop => prop . kind === ts . SyntaxKind . PropertyAssignment )
90+ . filter ( ( prop : ts . PropertyAssignment ) => {
91+ const name = prop . name ;
92+ switch ( name . kind ) {
93+ case ts . SyntaxKind . Identifier :
94+ return ( name as ts . Identifier ) . getText ( moduleSource ) === metadataField ;
95+ case ts . SyntaxKind . StringLiteral :
96+ return ( name as ts . StringLiteral ) . text === metadataField ;
97+ }
98+
99+ return false ;
100+ } ) ;
101+
102+ if ( ! matchingProperties ) {
103+ return [ ] ;
104+ }
105+
106+ if ( matchingProperties . length ) {
107+ const assignment = matchingProperties [ 0 ] as ts . PropertyAssignment ;
108+ if ( assignment . initializer . kind !== ts . SyntaxKind . ArrayLiteralExpression ) {
109+ return [ ] ;
110+ }
111+ const arrLiteral = assignment . initializer as ts . ArrayLiteralExpression ;
112+ if ( arrLiteral . elements . length === 0 ) {
113+ return addProvide ;
114+ } else {
115+ node = arrLiteral . elements . filter ( e => e . getText && e . getText ( ) . includes ( 'NZ_I18N' ) ) ;
116+ if ( node . length === 0 ) {
117+ return addProvide ;
118+ }
119+ return node . map ( e => new ReplaceChange ( modulePath , e . getStart ( ) , e . getText ( ) , `{ provide: NZ_I18N, useValue: ${ locale } }` ) ) ;
120+ }
121+ } else {
122+ return addProvide ;
123+ }
124+
125+ }
126+
127+ /** 注册 ng 国际化 */
128+ function registerLocaleData ( moduleSource : ts . SourceFile , modulePath : string , locale : string ) : Change {
129+ const allImports = findNodes ( moduleSource , ts . SyntaxKind . ImportDeclaration ) ;
130+ const allFun = findNodes ( moduleSource , ts . SyntaxKind . ExpressionStatement ) ;
131+ const registerLocaleDataFun = allFun . filter ( node => {
132+ const fun = node . getChildren ( ) ;
133+ return fun [ 0 ] . getChildren ( ) [ 0 ] && fun [ 0 ] . getChildren ( ) [ 0 ] . getText ( ) === 'registerLocaleData' ;
134+ } ) ;
135+ return registerLocaleDataFun . length === 0
136+ ? insertAfterLastOccurrence ( allImports , `\n\nregisterLocaleData(${ locale } );` , modulePath , 0 )
137+ : new ReplaceChange ( modulePath , registerLocaleDataFun [ 0 ] . getStart ( ) , registerLocaleDataFun [ 0 ] . getText ( ) , `registerLocaleData(${ locale } );` ) ;
138+ }
139+
68140/** 降级 less */
69141function downgradeLess ( ) : ( host : Tree ) => Tree {
70142 return ( host : Tree ) => {
@@ -90,7 +162,7 @@ function addModulesToAppModule(options: Schema): (host: Tree) => Tree {
90162 addModuleImportToRootModule ( host , 'BrowserAnimationsModule' , '@angular/platform-browser/animations' , project ) ;
91163 addModuleImportToRootModule ( host , 'FormsModule' , '@angular/forms' , project ) ;
92164 addModuleImportToRootModule ( host , 'HttpClientModule' , '@angular/common/http' , project ) ;
93- addModuleImportToRootModule ( host , 'NgZorroAntdModule.forRoot() ' , 'ng-zorro-antd' , project ) ;
165+ addModuleImportToRootModule ( host , 'NgZorroAntdModule' , 'ng-zorro-antd' , project ) ;
94166
95167 return host ;
96168 } ;
@@ -113,7 +185,16 @@ export function addThemeToAppStyles(options: Schema): (host: Tree) => Tree {
113185/** 将预设样式写入 theme.less,并添加到 angular.json */
114186function insertCustomTheme ( project : Project , host : Tree , workspace : Workspace ) : void {
115187 const themePath = 'src/theme.less' ;
116- host . create ( themePath , createCustomTheme ( ) ) ;
188+ const customTheme = createCustomTheme ( ) ;
189+ if ( host . exists ( themePath ) ) {
190+ const beforeContent = host . read ( themePath ) . toString ( 'utf8' ) ;
191+ if ( beforeContent . indexOf ( customTheme ) === - 1 ) {
192+ host . overwrite ( themePath , `${ customTheme } \n${ beforeContent } ` ) ;
193+ }
194+ } else {
195+ host . create ( themePath , createCustomTheme ( ) ) ;
196+ }
197+
117198 if ( project . architect ) {
118199 addStyleToTarget ( project . architect . build , host , themePath , workspace ) ;
119200 addStyleToTarget ( project . architect . test , host , themePath , workspace ) ;
0 commit comments