1717import 'reflect-metadata' ;
1818
1919import * as compiler from '@angular/compiler' ;
20- import { Component , NgModule , ViewEncapsulation } from '@angular/core ' ;
20+ import * as tsc from '@angular/tsc-wrapped ' ;
2121import * as path from 'path' ;
2222import * as ts from 'typescript' ;
23- import * as tsc from '@angular/tsc-wrapped' ;
24- import { Console } from './private_import_core' ;
25- import { ReflectorHost , ReflectorHostContext } from './reflector_host' ;
26- import { StaticAndDynamicReflectionCapabilities } from './static_reflection_capabilities' ;
27- import { StaticReflector , StaticSymbol } from './static_reflector' ;
23+
24+ import { Extractor } from './extractor' ;
2825
2926function extract (
3027 ngOptions : tsc . AngularCompilerOptions , cliOptions : tsc . I18nExtractionCliOptions ,
3128 program : ts . Program , host : ts . CompilerHost ) {
32- const htmlParser = new compiler . I18NHtmlParser ( new compiler . HtmlParser ( ) ) ;
33- const extractor = Extractor . create ( ngOptions , cliOptions . i18nFormat , program , host , htmlParser ) ;
29+ const resourceLoader : compiler . ResourceLoader = {
30+ get : ( s : string ) => {
31+ if ( ! host . fileExists ( s ) ) {
32+ // TODO: We should really have a test for error cases like this!
33+ throw new Error ( `Compilation failed. Resource file not found: ${ s } ` ) ;
34+ }
35+ return Promise . resolve ( host . readFile ( s ) ) ;
36+ }
37+ } ;
38+ const extractor =
39+ Extractor . create ( ngOptions , cliOptions . i18nFormat , program , host , resourceLoader ) ;
40+
3441 const bundlePromise : Promise < compiler . MessageBundle > = extractor.extract();
3542
3643 return (bundlePromise).then(messageBundle => {
@@ -46,6 +53,7 @@ function extract(
4653 case 'xliff' :
4754 case 'xlf' :
4855 default :
56+ const htmlParser = new compiler . I18NHtmlParser ( new compiler . HtmlParser ( ) ) ;
4957 ext = 'xlf' ;
5058 serializer = new compiler . Xliff ( htmlParser , compiler . DEFAULT_INTERPOLATION_CONFIG ) ;
5159 break ;
@@ -56,139 +64,6 @@ function extract(
5664 } ) ;
5765}
5866
59- const GENERATED_FILES = / \. n g f a c t o r y \. t s $ | \. c s s \. t s $ | \. c s s \. s h i m \. t s $ / ;
60-
61- export class Extractor {
62- constructor (
63- private program : ts . Program , public host : ts . CompilerHost ,
64- private staticReflector : StaticReflector , private messageBundle : compiler . MessageBundle ,
65- private reflectorHost : ReflectorHost ,
66- private metadataResolver : compiler . CompileMetadataResolver ,
67- private directiveNormalizer : compiler . DirectiveNormalizer ) { }
68-
69- private readFileMetadata ( absSourcePath : string ) : FileMetadata {
70- const moduleMetadata = this . staticReflector . getModuleMetadata ( absSourcePath ) ;
71- const result : FileMetadata = { components : [ ] , ngModules : [ ] , fileUrl : absSourcePath } ;
72- if ( ! moduleMetadata ) {
73- console . log ( `WARNING: no metadata found for ${ absSourcePath } ` ) ;
74- return result ;
75- }
76- const metadata = moduleMetadata [ 'metadata' ] ;
77- const symbols = metadata && Object . keys ( metadata ) ;
78- if ( ! symbols || ! symbols . length ) {
79- return result ;
80- }
81- for ( const symbol of symbols ) {
82- if ( metadata [ symbol ] && metadata [ symbol ] . __symbolic == 'error' ) {
83- // Ignore symbols that are only included to record error information.
84- continue ;
85- }
86- const staticType = this . reflectorHost . findDeclaration ( absSourcePath , symbol , absSourcePath ) ;
87- const annotations = this . staticReflector . annotations ( staticType ) ;
88- annotations . forEach ( ( annotation ) => {
89- if ( annotation instanceof NgModule ) {
90- result . ngModules . push ( staticType ) ;
91- } else if ( annotation instanceof Component ) {
92- result . components . push ( staticType ) ;
93- }
94- } ) ;
95- }
96- return result ;
97- }
98-
99- extract ( ) : Promise < compiler . MessageBundle > {
100- const filePaths =
101- this . program . getSourceFiles ( ) . map ( sf => sf . fileName ) . filter ( f => ! GENERATED_FILES . test ( f ) ) ;
102- const fileMetas = filePaths . map ( ( filePath ) => this . readFileMetadata ( filePath ) ) ;
103- const ngModules = fileMetas . reduce ( ( ngModules , fileMeta ) => {
104- ngModules . push ( ...fileMeta . ngModules ) ;
105- return ngModules ;
106- } , < StaticSymbol [ ] > []);
107- const analyzedNgModules = compiler.analyzeModules(ngModules, this.metadataResolver);
108- const errors: compiler.ParseError[] = [];
109-
110- let bundlePromise =
111- Promise
112- .all(fileMetas.map((fileMeta) => {
113- const url = fileMeta . fileUrl ;
114- return Promise . all ( fileMeta . components . map ( compType => {
115- const compMeta = this . metadataResolver . getDirectiveMetadata ( < any > compType);
116- const ngModule = analyzedNgModules.ngModuleByDirective.get(compType);
117- if (!ngModule) {
118- throw new Error (
119- `Cannot determine the module for component ${ compMeta . type . name } !` ) ;
120- }
121- return Promise
122- .all([compMeta, ...ngModule.transitiveModule.directives].map(
123- dirMeta =>
124- this . directiveNormalizer . normalizeDirective ( dirMeta ) . asyncResult ) )
125- . then ( ( normalizedCompWithDirectives ) => {
126- const compMeta = normalizedCompWithDirectives [ 0 ] ;
127- const html = compMeta . template . template ;
128- const interpolationConfig =
129- compiler . InterpolationConfig . fromArray ( compMeta . template . interpolation ) ;
130- errors . push (
131- ...this . messageBundle . updateFromTemplate ( html , url , interpolationConfig ) ) ;
132- } ) ;
133- } ) ) ;
134- } ))
135- .then(_ => this . messageBundle ) ;
136-
137- if ( errors . length ) {
138- throw new Error ( errors . map ( e => e . toString ( ) ) . join ( '\n' ) ) ;
139- }
140-
141- return bundlePromise;
142- }
143-
144- static create (
145- options : tsc . AngularCompilerOptions , translationsFormat : string , program : ts . Program ,
146- compilerHost : ts . CompilerHost , htmlParser : compiler . I18NHtmlParser ,
147- reflectorHostContext ?: ReflectorHostContext ) : Extractor {
148- const resourceLoader : compiler . ResourceLoader = {
149- get : ( s : string ) => {
150- if ( ! compilerHost . fileExists ( s ) ) {
151- // TODO: We should really have a test for error cases like this!
152- throw new Error ( `Compilation failed. Resource file not found: ${ s } ` ) ;
153- }
154- return Promise . resolve ( compilerHost . readFile ( s ) ) ;
155- }
156- } ;
157-
158- const urlResolver : compiler . UrlResolver = compiler . createOfflineCompileUrlResolver ( ) ;
159- const reflectorHost = new ReflectorHost ( program , compilerHost , options , reflectorHostContext ) ;
160- const staticReflector = new StaticReflector ( reflectorHost ) ;
161- StaticAndDynamicReflectionCapabilities . install ( staticReflector ) ;
162-
163- const config = new compiler . CompilerConfig ( {
164- genDebugInfo : options . debug === true ,
165- defaultEncapsulation : ViewEncapsulation . Emulated ,
166- logBindingUpdate : false ,
167- useJit : false
168- } ) ;
169-
170- const normalizer =
171- new compiler . DirectiveNormalizer ( resourceLoader , urlResolver , htmlParser , config ) ;
172- const elementSchemaRegistry = new compiler . DomElementSchemaRegistry ( ) ;
173- const resolver = new compiler . CompileMetadataResolver (
174- new compiler . NgModuleResolver ( staticReflector ) ,
175- new compiler . DirectiveResolver ( staticReflector ) , new compiler . PipeResolver ( staticReflector ) ,
176- elementSchemaRegistry , staticReflector ) ;
177-
178- // TODO(vicb): implicit tags & attributes
179- let messageBundle = new compiler . MessageBundle ( htmlParser , [ ] , { } ) ;
180-
181- return new Extractor (
182- program , compilerHost , staticReflector , messageBundle , reflectorHost , resolver , normalizer ) ;
183- }
184- }
185-
186- interface FileMetadata {
187- fileUrl : string ;
188- components : StaticSymbol [ ] ;
189- ngModules : StaticSymbol [ ] ;
190- }
191-
19267// Entry point
19368if ( require . main === module ) {
19469 const args = require ( 'minimist' ) ( process . argv . slice ( 2 ) ) ;
0 commit comments