@@ -19,6 +19,7 @@ import templateBuilder from '@babel/template';
19
19
import { createHash } from 'crypto' ;
20
20
import * as fs from 'fs' ;
21
21
import * as path from 'path' ;
22
+ import { lt as semverLt } from 'semver' ;
22
23
import { RawSourceMap , SourceMapConsumer , SourceMapGenerator } from 'source-map' ;
23
24
import { minify } from 'terser' ;
24
25
import * as v8 from 'v8' ;
@@ -32,6 +33,8 @@ import {
32
33
import { allowMangle , allowMinify , shouldBeautify } from './environment-options' ;
33
34
import { I18nOptions } from './i18n-options' ;
34
35
36
+ type LocalizeUtilities = typeof import ( '@angular/localize/src/tools/src/source_file_utils' ) ;
37
+
35
38
const cacache = require ( 'cacache' ) ;
36
39
const deserialize = ( ( v8 as unknown ) as { deserialize ( buffer : Buffer ) : unknown } ) . deserialize ;
37
40
@@ -547,7 +550,6 @@ export async function createI18nPlugins(
547
550
localeDataContent ?: string ,
548
551
) {
549
552
const plugins = [ ] ;
550
- // tslint:disable-next-line: no-implicit-dependencies
551
553
const localizeDiag = await import ( '@angular/localize/src/tools/src/diagnostics' ) ;
552
554
553
555
const diagnostics = new localizeDiag . Diagnostics ( ) ;
@@ -723,9 +725,7 @@ async function inlineLocalesDirect(ast: ParseResult, options: InlineOptions) {
723
725
724
726
const { default : generate } = await import ( '@babel/generator' ) ;
725
727
726
- // tslint:disable-next-line: no-implicit-dependencies
727
728
const utils = await import ( '@angular/localize/src/tools/src/source_file_utils' ) ;
728
- // tslint:disable-next-line: no-implicit-dependencies
729
729
const localizeDiag = await import ( '@angular/localize/src/tools/src/diagnostics' ) ;
730
730
731
731
const diagnostics = new localizeDiag . Diagnostics ( ) ;
@@ -829,21 +829,24 @@ function inlineCopyOnly(options: InlineOptions) {
829
829
function findLocalizePositions (
830
830
ast : ParseResult ,
831
831
options : InlineOptions ,
832
- // tslint:disable-next-line: no-implicit-dependencies
833
- utils : typeof import ( '@angular/localize/src/tools/src/source_file_utils' ) ,
832
+ utils : LocalizeUtilities ,
834
833
) : LocalizePosition [ ] {
835
834
const positions : LocalizePosition [ ] = [ ] ;
835
+
836
+ // Workaround to ensure a path hub is present for traversal
837
+ const { File } = require ( '@babel/core' ) ;
838
+ const file = new File ( { } , { code : options . code , ast } ) ;
839
+
836
840
if ( options . es5 ) {
837
- traverse ( ast , {
838
- CallExpression ( path : NodePath < types . CallExpression > ) {
841
+ traverse ( file . ast , {
842
+ CallExpression ( path ) {
839
843
const callee = path . get ( 'callee' ) ;
840
844
if (
841
845
callee . isIdentifier ( ) &&
842
846
callee . node . name === localizeName &&
843
847
utils . isGlobalIdentifier ( callee )
844
848
) {
845
- const messageParts = utils . unwrapMessagePartsFromLocalizeCall ( path ) ;
846
- const expressions = utils . unwrapSubstitutionsFromLocalizeCall ( path . node ) ;
849
+ const [ messageParts , expressions ] = unwrapLocalizeCall ( path , utils ) ;
847
850
positions . push ( {
848
851
// tslint:disable-next-line: no-non-null-assertion
849
852
start : path . node . start ! ,
@@ -856,32 +859,80 @@ function findLocalizePositions(
856
859
} ,
857
860
} ) ;
858
861
} else {
859
- const traverseFast = ( ( types as unknown ) as {
860
- traverseFast : ( node : types . Node , enter : ( node : types . Node ) => void ) => void ;
861
- } ) . traverseFast ;
862
-
863
- traverseFast ( ast , node => {
864
- if (
865
- node . type === 'TaggedTemplateExpression' &&
866
- types . isIdentifier ( node . tag ) &&
867
- node . tag . name === localizeName
868
- ) {
869
- const messageParts = utils . unwrapMessagePartsFromTemplateLiteral ( node . quasi . quasis ) ;
870
- positions . push ( {
871
- // tslint:disable-next-line: no-non-null-assertion
872
- start : node . start ! ,
873
- // tslint:disable-next-line: no-non-null-assertion
874
- end : node . end ! ,
875
- messageParts,
876
- expressions : node . quasi . expressions ,
877
- } ) ;
878
- }
862
+ traverse ( file . ast , {
863
+ TaggedTemplateExpression ( path ) {
864
+ if ( types . isIdentifier ( path . node . tag ) && path . node . tag . name === localizeName ) {
865
+ const [ messageParts , expressions ] = unwrapTemplateLiteral ( path , utils ) ;
866
+ positions . push ( {
867
+ // tslint:disable-next-line: no-non-null-assertion
868
+ start : path . node . start ! ,
869
+ // tslint:disable-next-line: no-non-null-assertion
870
+ end : path . node . end ! ,
871
+ messageParts,
872
+ expressions,
873
+ } ) ;
874
+ }
875
+ } ,
879
876
} ) ;
880
877
}
881
878
882
879
return positions ;
883
880
}
884
881
882
+ // TODO: Remove this for v11.
883
+ // This check allows the CLI to support both FW 10.0 and 10.1
884
+ let localizeOld : boolean | undefined ;
885
+
886
+ function unwrapTemplateLiteral (
887
+ path : NodePath < types . TemplateLiteral > ,
888
+ utils : LocalizeUtilities ,
889
+ ) : [ TemplateStringsArray , types . Expression [ ] ] {
890
+ if ( localizeOld === undefined ) {
891
+ const { version : localizeVersion } = require ( '@angular/localize/package.json' ) ;
892
+ localizeOld = semverLt ( localizeVersion , '10.1.0-rc.0' , { includePrerelease : true } ) ;
893
+ }
894
+
895
+ if ( localizeOld ) {
896
+ // tslint:disable-next-line: no-any
897
+ const messageParts = utils . unwrapMessagePartsFromTemplateLiteral ( path . node . quasi . quasis as any ) ;
898
+
899
+ return [ ( messageParts as unknown ) as TemplateStringsArray , path . node . quasi . expressions ] ;
900
+ }
901
+
902
+ const [ messageParts ] = utils . unwrapMessagePartsFromTemplateLiteral (
903
+ path . get ( 'quasi' ) . get ( 'quasis' ) ,
904
+ ) ;
905
+ const [ expressions ] = utils . unwrapExpressionsFromTemplateLiteral ( path . get ( 'quasi' ) ) ;
906
+
907
+ return [ messageParts , expressions ] ;
908
+ }
909
+
910
+ function unwrapLocalizeCall (
911
+ path : NodePath < types . CallExpression > ,
912
+ utils : LocalizeUtilities ,
913
+ ) : [ TemplateStringsArray , types . Expression [ ] ] {
914
+ if ( localizeOld === undefined ) {
915
+ const { version : localizeVersion } = require ( '@angular/localize/package.json' ) ;
916
+ localizeOld = semverLt ( localizeVersion , '10.1.0-rc.0' , { includePrerelease : true } ) ;
917
+ }
918
+
919
+ if ( localizeOld ) {
920
+ const messageParts = utils . unwrapMessagePartsFromLocalizeCall ( path ) ;
921
+ // tslint:disable-next-line: no-any
922
+ const expressions = utils . unwrapSubstitutionsFromLocalizeCall ( path . node as any ) ;
923
+
924
+ return [
925
+ ( messageParts as unknown ) as TemplateStringsArray ,
926
+ ( expressions as unknown ) as types . Expression [ ] ,
927
+ ] ;
928
+ }
929
+
930
+ const [ messageParts ] = utils . unwrapMessagePartsFromLocalizeCall ( path ) ;
931
+ const [ expressions ] = utils . unwrapSubstitutionsFromLocalizeCall ( path ) ;
932
+
933
+ return [ messageParts , expressions ] ;
934
+ }
935
+
885
936
async function loadLocaleData ( path : string , optimize : boolean , es5 : boolean ) : Promise < string > {
886
937
// The path is validated during option processing before the build starts
887
938
const content = fs . readFileSync ( path , 'utf8' ) ;
0 commit comments