/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/localize/tools/src/extract/extraction.ts
143 строки
5 KB
Angular Robot
build: update babel monorepo to v8
07 июл 2026, 00:05
07 июл 2026, 00:05
731d665
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import { AbsoluteFsPath, Logger, ReadonlyFileSystem, SourceFile, SourceFileLoader, } from '@angular/compiler-cli/private/localize'; import {transformSync} from '@babel/core'; import {ɵParsedMessage, ɵSourceLocation} from '../../../index'; import {makeEs2015ExtractPlugin} from './source_files/es2015_extract_plugin'; import {makeEs5ExtractPlugin} from './source_files/es5_extract_plugin'; export interface ExtractionOptions { basePath: AbsoluteFsPath; useSourceMaps?: boolean; localizeName?: string; } /** * Extracts parsed messages from file contents, by parsing the contents as JavaScript * and looking for occurrences of `$localize` in the source code. * * @publicApi used by CLI */ export class MessageExtractor { private basePath: AbsoluteFsPath; private useSourceMaps: boolean; private localizeName: string; private loader: SourceFileLoader; constructor( private fs: ReadonlyFileSystem, private logger: Logger, {basePath, useSourceMaps = true, localizeName = '$localize'}: ExtractionOptions, ) { this.basePath = basePath; this.useSourceMaps = useSourceMaps; this.localizeName = localizeName; this.loader = new SourceFileLoader(this.fs, this.logger, {webpack: basePath}); } extractMessages(filename: string): ɵParsedMessage[] { const messages: ɵParsedMessage[] = []; const sourceCode = this.fs.readFile(this.fs.resolve(this.basePath, filename)); if (sourceCode.includes(this.localizeName)) { // Only bother to parse the file if it contains a reference to `$localize`. transformSync(sourceCode, { sourceRoot: this.basePath, filename, plugins: [ () => makeEs2015ExtractPlugin(this.fs, messages, this.localizeName), () => makeEs5ExtractPlugin(this.fs, messages, this.localizeName), ], code: false, ast: false, }); if (this.useSourceMaps && messages.length > 0) { this.updateSourceLocations(filename, sourceCode, messages); } } return messages; } /** * Update the location of each message to point to the source-mapped original source location, if * available. */ private updateSourceLocations( filename: string, contents: string, messages: ɵParsedMessage[], ): void { const sourceFile = this.loader.loadSourceFile( this.fs.resolve(this.basePath, filename), contents, ); if (sourceFile === null) { return; } for (const message of messages) { if (message.location !== undefined) { message.location = this.getOriginalLocation(sourceFile, message.location); if (message.messagePartLocations) { message.messagePartLocations = message.messagePartLocations.map( (location) => location && this.getOriginalLocation(sourceFile, location), ); } if (message.substitutionLocations) { const placeholderNames = Object.keys(message.substitutionLocations); for (const placeholderName of placeholderNames) { const location = message.substitutionLocations[placeholderName]; message.substitutionLocations[placeholderName] = location && this.getOriginalLocation(sourceFile, location); } } } } } /** * Find the original location using source-maps if available. * * @param sourceFile The generated `sourceFile` that contains the `location`. * @param location The location within the generated `sourceFile` that needs mapping. * * @returns A new location that refers to the original source location mapped from the given * `location` in the generated `sourceFile`. */ private getOriginalLocation(sourceFile: SourceFile, location: ɵSourceLocation): ɵSourceLocation { const originalStart = sourceFile.getOriginalLocation( location.start.line, location.start.column, ); if (originalStart === null) { return location; } const originalEnd = sourceFile.getOriginalLocation(location.end.line, location.end.column); const start = {line: originalStart.line, column: originalStart.column}; // We check whether the files are the same, since the returned location can only have a single // `file` and it would not make sense to store the end position from a different source file. const end = originalEnd !== null && originalEnd.file === originalStart.file ? {line: originalEnd.line, column: originalEnd.column} : start; const originalSourceFile = sourceFile.sources.find( (sf) => sf?.sourcePath === originalStart.file, )!; const startPos = originalSourceFile.startOfLinePositions[start.line] + start.column; const endPos = originalSourceFile.startOfLinePositions[end.line] + end.column; const text = originalSourceFile.contents.substring(startPos, endPos).trim(); return {file: originalStart.file, start, end, text}; } }