@@ -12,6 +12,7 @@ import * as path from 'path';
12
12
import { RawSourceMap , SourceMapConsumer , SourceMapGenerator } from 'source-map' ;
13
13
import { minify } from 'terser' ;
14
14
import * as v8 from 'v8' ;
15
+ import { SourceMapSource } from 'webpack-sources' ;
15
16
import { I18nOptions } from './i18n-options' ;
16
17
import { manglingDisabled } from './mangle-options' ;
17
18
@@ -131,7 +132,7 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
131
132
downlevelCode = transformResult . code ;
132
133
133
134
if ( manualSourceMaps && sourceMap && transformResult . map ) {
134
- downlevelMap = await mergeSourcemaps ( sourceMap , transformResult . map ) ;
135
+ downlevelMap = await mergeSourceMapsFast ( sourceMap , transformResult . map ) ;
135
136
} else {
136
137
// undefined is needed here to normalize the property type
137
138
downlevelMap = transformResult . map || undefined ;
@@ -196,7 +197,28 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
196
197
return result ;
197
198
}
198
199
199
- async function mergeSourcemaps ( first : RawSourceMap , second : RawSourceMap ) {
200
+ function mergeSourceMaps (
201
+ inputCode : string ,
202
+ inputSourceMap : RawSourceMap ,
203
+ resultCode : string ,
204
+ resultSourceMap : RawSourceMap ,
205
+ filename : string ,
206
+ ) : RawSourceMap {
207
+ // More accurate but significantly more costly
208
+
209
+ // The last argument is not yet in the typings
210
+ // tslint:disable-next-line: no-any
211
+ return new ( SourceMapSource as any ) (
212
+ resultCode ,
213
+ filename ,
214
+ resultSourceMap ,
215
+ inputCode ,
216
+ inputSourceMap ,
217
+ true ,
218
+ ) . map ( ) ;
219
+ }
220
+
221
+ async function mergeSourceMapsFast ( first : RawSourceMap , second : RawSourceMap ) {
200
222
const sourceRoot = first . sourceRoot ;
201
223
const generator = new SourceMapGenerator ( ) ;
202
224
@@ -446,6 +468,7 @@ async function processRuntime(
446
468
export interface InlineOptions {
447
469
filename : string ;
448
470
code : string ;
471
+ map ?: string ;
449
472
es5 : boolean ;
450
473
outputPath : string ;
451
474
missingTranslation ?: 'warning' | 'error' | 'ignore' ;
@@ -469,14 +492,7 @@ export async function inlineLocales(options: InlineOptions) {
469
492
}
470
493
471
494
if ( ! options . code . includes ( localizeName ) ) {
472
- for ( const locale of i18n . inlineLocales ) {
473
- fs . writeFileSync (
474
- path . join ( options . outputPath , i18n . flatOutput ? '' : locale , options . filename ) ,
475
- options . code ,
476
- ) ;
477
- }
478
-
479
- return { file : options . filename , diagnostics : [ ] , count : 0 } ;
495
+ return inlineCopyOnly ( options ) ;
480
496
}
481
497
482
498
const { default : MagicString } = await import ( 'magic-string' ) ;
@@ -490,7 +506,12 @@ export async function inlineLocales(options: InlineOptions) {
490
506
const diagnostics = new localizeDiag . Diagnostics ( ) ;
491
507
492
508
const positions = findLocalizePositions ( options , utils ) ;
509
+ if ( positions . length === 0 ) {
510
+ return inlineCopyOnly ( options ) ;
511
+ }
512
+
493
513
const content = new MagicString ( options . code ) ;
514
+ const inputMap = options . map && JSON . parse ( options . map ) as RawSourceMap ;
494
515
495
516
for ( const locale of i18n . inlineLocales ) {
496
517
const isSourceLocale = locale === i18n . sourceLocale ;
@@ -512,15 +533,46 @@ export async function inlineLocales(options: InlineOptions) {
512
533
}
513
534
514
535
const output = content . toString ( ) ;
515
- fs . writeFileSync (
516
- path . join ( options . outputPath , i18n . flatOutput ? '' : locale , options . filename ) ,
517
- output ,
536
+ const outputPath = path . join (
537
+ options . outputPath ,
538
+ i18n . flatOutput ? '' : locale ,
539
+ options . filename ,
518
540
) ;
541
+ fs . writeFileSync ( outputPath , output ) ;
542
+
543
+ if ( inputMap ) {
544
+ const contentMap = content . generateMap ( ) ;
545
+ const outputMap = mergeSourceMaps (
546
+ options . code ,
547
+ inputMap ,
548
+ output ,
549
+ contentMap ,
550
+ options . filename ,
551
+ ) ;
552
+
553
+ fs . writeFileSync ( outputPath + '.map' , JSON . stringify ( outputMap ) ) ;
554
+ }
519
555
}
520
556
521
557
return { file : options . filename , diagnostics : diagnostics . messages , count : positions . length } ;
522
558
}
523
559
560
+ function inlineCopyOnly ( options : InlineOptions ) {
561
+ if ( ! i18n ) {
562
+ throw new Error ( 'i18n options are missing' ) ;
563
+ }
564
+
565
+ for ( const locale of i18n . inlineLocales ) {
566
+ const outputPath = path . join ( options . outputPath , i18n . flatOutput ? '' : locale , options . filename ) ;
567
+ fs . writeFileSync ( outputPath , options . code ) ;
568
+ if ( options . map ) {
569
+ fs . writeFileSync ( outputPath + '.map' , options . map ) ;
570
+ }
571
+ }
572
+
573
+ return { file : options . filename , diagnostics : [ ] , count : 0 } ;
574
+ }
575
+
524
576
function findLocalizePositions (
525
577
options : InlineOptions ,
526
578
utils : typeof import ( '@angular/localize/src/tools/src/translate/source_files/source_file_utils' ) ,
@@ -536,10 +588,7 @@ function findLocalizePositions(
536
588
traverse ( ast , {
537
589
CallExpression ( path : NodePath < types . CallExpression > ) {
538
590
const callee = path . get ( 'callee' ) ;
539
- if (
540
- callee . isIdentifier ( ) &&
541
- callee . node . name === localizeName
542
- ) {
591
+ if ( callee . isIdentifier ( ) && callee . node . name === localizeName ) {
543
592
const messageParts = utils . unwrapMessagePartsFromLocalizeCall ( path ) ;
544
593
const expressions = utils . unwrapSubstitutionsFromLocalizeCall ( path . node ) ;
545
594
positions . push ( {
0 commit comments