mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(compiler): Remove the interpolation config (#64071)
After #63474, we don't need that anymore. PR Close #64071
This commit is contained in:
parent
fc643c9044
commit
04462ed67f
34 changed files with 74 additions and 339 deletions
|
|
@ -10,10 +10,8 @@ import {
|
|||
compileComponentFromMetadata,
|
||||
ConstantPool,
|
||||
DeclarationListEmitMode,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
DeferBlockDepsEmitMode,
|
||||
ForwardRefHandling,
|
||||
InterpolationConfig,
|
||||
makeBindingParser,
|
||||
outputAst as o,
|
||||
ParsedTemplate,
|
||||
|
|
@ -95,7 +93,6 @@ export class PartialComponentLinkerVersion1<TStatement, TExpression>
|
|||
metaObj: AstObject<R3DeclareComponentMetadata, TExpression>,
|
||||
version: string,
|
||||
): R3ComponentMetadata<R3TemplateDependencyMetadata> {
|
||||
const interpolation = parseInterpolationConfig(metaObj);
|
||||
const templateSource = metaObj.getValue('template');
|
||||
const isInline = metaObj.has('isInline') ? metaObj.getBoolean('isInline') : false;
|
||||
const templateInfo = this.getTemplateInfo(templateSource, isInline);
|
||||
|
|
@ -109,7 +106,6 @@ export class PartialComponentLinkerVersion1<TStatement, TExpression>
|
|||
|
||||
const template = parseTemplate(templateInfo.code, templateInfo.sourceUrl, {
|
||||
escapedString: templateInfo.isEscaped,
|
||||
interpolationConfig: interpolation,
|
||||
range: templateInfo.range,
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
preserveWhitespaces: metaObj.has('preserveWhitespaces')
|
||||
|
|
@ -244,7 +240,6 @@ export class PartialComponentLinkerVersion1<TStatement, TExpression>
|
|||
encapsulation: metaObj.has('encapsulation')
|
||||
? parseEncapsulation(metaObj.getValue('encapsulation'))
|
||||
: ViewEncapsulation.Emulated,
|
||||
interpolation,
|
||||
changeDetection: metaObj.has('changeDetection')
|
||||
? parseChangeDetectionStrategy(metaObj.getValue('changeDetection'))
|
||||
: ChangeDetectionStrategy.Default,
|
||||
|
|
@ -380,27 +375,6 @@ interface TemplateInfo {
|
|||
isEscaped: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an `InterpolationConfig` from the component declaration.
|
||||
*/
|
||||
function parseInterpolationConfig<TExpression>(
|
||||
metaObj: AstObject<R3DeclareComponentMetadata, TExpression>,
|
||||
): InterpolationConfig {
|
||||
if (!metaObj.has('interpolation')) {
|
||||
return DEFAULT_INTERPOLATION_CONFIG;
|
||||
}
|
||||
|
||||
const interpolationExpr = metaObj.getValue('interpolation');
|
||||
const values = interpolationExpr.getArray().map((entry) => entry.getString());
|
||||
if (values.length !== 2) {
|
||||
throw new FatalLinkerError(
|
||||
interpolationExpr.expression,
|
||||
'Unsupported interpolation config, expected an array containing exactly two strings',
|
||||
);
|
||||
}
|
||||
return InterpolationConfig.fromArray(values as [string, string]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the `ViewEncapsulation` mode from the AST value's symbol name.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import {
|
|||
CssSelector,
|
||||
DeclarationListEmitMode,
|
||||
DeclareComponentTemplateInfo,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
DeferBlockDepsEmitMode,
|
||||
DomElementSchemaRegistry,
|
||||
ExternalExpr,
|
||||
|
|
@ -955,7 +954,6 @@ export class ComponentDecoratorHandler
|
|||
template,
|
||||
encapsulation,
|
||||
changeDetection,
|
||||
interpolation: template.interpolationConfig ?? DEFAULT_INTERPOLATION_CONFIG,
|
||||
styles,
|
||||
externalStyles,
|
||||
// These will be replaced during the compilation step, after all `NgModule`s have been
|
||||
|
|
@ -1349,7 +1347,6 @@ export class ComponentDecoratorHandler
|
|||
ctx.updateFromTemplate(
|
||||
analysis.template.content,
|
||||
analysis.template.declaration.resolvedTemplateUrl,
|
||||
analysis.template.interpolationConfig ?? DEFAULT_INTERPOLATION_CONFIG,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2473,7 +2470,7 @@ export class ComponentDecoratorHandler
|
|||
|
||||
/** Creates a new binding parser. */
|
||||
private getNewBindingParser() {
|
||||
return makeBindingParser(undefined, this.enableSelectorless);
|
||||
return makeBindingParser(this.enableSelectorless);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
InterpolationConfig,
|
||||
LexerRange,
|
||||
ParsedTemplate,
|
||||
ParseSourceFile,
|
||||
|
|
@ -91,7 +89,6 @@ export interface ParsedTemplateWithSource extends ParsedComponentTemplate {
|
|||
*/
|
||||
interface CommonTemplateDeclaration {
|
||||
preserveWhitespaces: boolean;
|
||||
interpolationConfig: InterpolationConfig;
|
||||
templateUrl: string;
|
||||
resolvedTemplateUrl: string;
|
||||
}
|
||||
|
|
@ -284,7 +281,6 @@ export function createEmptyTemplate(
|
|||
declaration: templateUrl
|
||||
? {
|
||||
isInline: false,
|
||||
interpolationConfig: InterpolationConfig.fromArray(null),
|
||||
preserveWhitespaces: false,
|
||||
templateUrlExpression: templateUrl,
|
||||
templateUrl: 'missing.ng.html',
|
||||
|
|
@ -292,7 +288,6 @@ export function createEmptyTemplate(
|
|||
}
|
||||
: {
|
||||
isInline: true,
|
||||
interpolationConfig: InterpolationConfig.fromArray(null),
|
||||
preserveWhitespaces: false,
|
||||
expression: template!,
|
||||
templateUrl: containingFile,
|
||||
|
|
@ -312,7 +307,6 @@ function parseExtractedTemplate(
|
|||
// We always normalize line endings if the template has been escaped (i.e. is inline).
|
||||
const i18nNormalizeLineEndingsInICUs = escapedString || options.i18nNormalizeLineEndingsInICUs;
|
||||
const commonParseOptions: ParseTemplateOptions = {
|
||||
interpolationConfig: template.interpolationConfig,
|
||||
range: sourceParseRange ?? undefined,
|
||||
enableI18nLegacyMessageIdFormat: options.enableI18nLegacyMessageIdFormat,
|
||||
i18nNormalizeLineEndingsInICUs,
|
||||
|
|
@ -379,7 +373,6 @@ export function parseTemplateDeclaration(
|
|||
preserveWhitespaces = value;
|
||||
}
|
||||
|
||||
let interpolationConfig = DEFAULT_INTERPOLATION_CONFIG;
|
||||
if (component.has('interpolation')) {
|
||||
const expr = component.get('interpolation')!;
|
||||
const value = evaluator.evaluate(expr);
|
||||
|
|
@ -394,7 +387,6 @@ export function parseTemplateDeclaration(
|
|||
'interpolation must be an array with 2 elements of string type',
|
||||
);
|
||||
}
|
||||
interpolationConfig = InterpolationConfig.fromArray(value as [string, string]);
|
||||
}
|
||||
|
||||
if (component.has('templateUrl')) {
|
||||
|
|
@ -411,7 +403,6 @@ export function parseTemplateDeclaration(
|
|||
const resourceUrl = resourceLoader.resolve(templateUrl, containingFile);
|
||||
return {
|
||||
isInline: false,
|
||||
interpolationConfig,
|
||||
preserveWhitespaces,
|
||||
templateUrl,
|
||||
templateUrlExpression: templateUrlExpr,
|
||||
|
|
@ -433,7 +424,6 @@ export function parseTemplateDeclaration(
|
|||
} else if (component.has('template')) {
|
||||
return {
|
||||
isInline: true,
|
||||
interpolationConfig,
|
||||
preserveWhitespaces,
|
||||
expression: component.get('template')!,
|
||||
templateUrl: containingFile,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {InterpolationConfig} from '@angular/compiler';
|
||||
|
||||
/**
|
||||
* Captures template information intended for extraction of i18n messages from a template.
|
||||
*
|
||||
|
|
@ -23,5 +21,5 @@ export interface Xi18nContext {
|
|||
* the return type is declared as `void` for simplicity, since any parse errors would be reported
|
||||
* as diagnostics anyway.
|
||||
*/
|
||||
updateFromTemplate(html: string, url: string, interpolationConfig: InterpolationConfig): void;
|
||||
updateFromTemplate(html: string, url: string): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
|
|||
styles: string[];
|
||||
encapsulation: ViewEncapsulation;
|
||||
viewProviders: Provider[] | null;
|
||||
interpolation?: [string, string];
|
||||
changeDetection?: ChangeDetectionStrategy;
|
||||
hasDirectiveDependencies: boolean;
|
||||
}
|
||||
|
|
@ -277,7 +276,6 @@ export interface R3DeclareComponentFacade extends R3DeclareDirectiveFacade {
|
|||
animations?: OpaqueValue;
|
||||
changeDetection?: ChangeDetectionStrategy;
|
||||
encapsulation?: ViewEncapsulation;
|
||||
interpolation?: [string, string];
|
||||
preserveWhitespaces?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import * as chars from '../chars';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/defaults';
|
||||
import {
|
||||
InterpolatedAttributeToken,
|
||||
InterpolatedTextToken,
|
||||
|
|
@ -103,10 +102,9 @@ export class Parser {
|
|||
input: string,
|
||||
parseSourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): ASTWithSource {
|
||||
const errors: ParseError[] = [];
|
||||
this._checkNoInterpolation(errors, input, parseSourceSpan, interpolationConfig);
|
||||
this._checkNoInterpolation(errors, input, parseSourceSpan);
|
||||
const {stripped: sourceToLex} = this._stripComments(input);
|
||||
const tokens = this._lexer.tokenize(sourceToLex);
|
||||
const ast = new _ParseAST(
|
||||
|
|
@ -127,16 +125,9 @@ export class Parser {
|
|||
input: string,
|
||||
parseSourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): ASTWithSource {
|
||||
const errors: ParseError[] = [];
|
||||
const ast = this._parseBindingAst(
|
||||
input,
|
||||
parseSourceSpan,
|
||||
absoluteOffset,
|
||||
interpolationConfig,
|
||||
errors,
|
||||
);
|
||||
const ast = this._parseBindingAst(input, parseSourceSpan, absoluteOffset, errors);
|
||||
return new ASTWithSource(ast, input, getLocation(parseSourceSpan), absoluteOffset, errors);
|
||||
}
|
||||
|
||||
|
|
@ -151,16 +142,9 @@ export class Parser {
|
|||
input: string,
|
||||
parseSourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): ASTWithSource {
|
||||
const errors: ParseError[] = [];
|
||||
const ast = this._parseBindingAst(
|
||||
input,
|
||||
parseSourceSpan,
|
||||
absoluteOffset,
|
||||
interpolationConfig,
|
||||
errors,
|
||||
);
|
||||
const ast = this._parseBindingAst(input, parseSourceSpan, absoluteOffset, errors);
|
||||
const simplExpressionErrors = this.checkSimpleExpression(ast);
|
||||
|
||||
if (simplExpressionErrors.length > 0) {
|
||||
|
|
@ -180,10 +164,9 @@ export class Parser {
|
|||
input: string,
|
||||
parseSourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number,
|
||||
interpolationConfig: InterpolationConfig,
|
||||
errors: ParseError[],
|
||||
): AST {
|
||||
this._checkNoInterpolation(errors, input, parseSourceSpan, interpolationConfig);
|
||||
this._checkNoInterpolation(errors, input, parseSourceSpan);
|
||||
const {stripped: sourceToLex} = this._stripComments(input);
|
||||
const tokens = this._lexer.tokenize(sourceToLex);
|
||||
return new _ParseAST(
|
||||
|
|
@ -254,7 +237,6 @@ export class Parser {
|
|||
parseSourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number,
|
||||
interpolatedTokens: InterpolatedAttributeToken[] | InterpolatedTextToken[] | null,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): ASTWithSource | null {
|
||||
const errors: ParseError[] = [];
|
||||
const {strings, expressions, offsets} = this.splitInterpolation(
|
||||
|
|
@ -262,7 +244,6 @@ export class Parser {
|
|||
parseSourceSpan,
|
||||
errors,
|
||||
interpolatedTokens,
|
||||
interpolationConfig,
|
||||
);
|
||||
if (expressions.length === 0) return null;
|
||||
|
||||
|
|
@ -377,7 +358,6 @@ export class Parser {
|
|||
parseSourceSpan: ParseSourceSpan,
|
||||
errors: ParseError[],
|
||||
interpolatedTokens: InterpolatedAttributeToken[] | InterpolatedTextToken[] | null,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): SplitInterpolation {
|
||||
const strings: InterpolationPiece[] = [];
|
||||
const expressions: InterpolationPiece[] = [];
|
||||
|
|
@ -388,7 +368,8 @@ export class Parser {
|
|||
let i = 0;
|
||||
let atInterpolation = false;
|
||||
let extendLastString = false;
|
||||
let {start: interpStart, end: interpEnd} = interpolationConfig;
|
||||
const interpStart = '{{';
|
||||
const interpEnd = '}}';
|
||||
while (i < input.length) {
|
||||
if (!atInterpolation) {
|
||||
// parse until starting {{
|
||||
|
|
@ -493,18 +474,17 @@ export class Parser {
|
|||
errors: ParseError[],
|
||||
input: string,
|
||||
parseSourceSpan: ParseSourceSpan,
|
||||
{start, end}: InterpolationConfig,
|
||||
): void {
|
||||
let startIndex = -1;
|
||||
let endIndex = -1;
|
||||
|
||||
for (const charIndex of this._forEachUnquotedChar(input, 0)) {
|
||||
if (startIndex === -1) {
|
||||
if (input.startsWith(start)) {
|
||||
if (input.startsWith('{{')) {
|
||||
startIndex = charIndex;
|
||||
}
|
||||
} else {
|
||||
endIndex = this._getInterpolationEndIndex(input, end, charIndex);
|
||||
endIndex = this._getInterpolationEndIndex(input, '}}', charIndex);
|
||||
if (endIndex > -1) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -514,7 +494,7 @@ export class Parser {
|
|||
if (startIndex > -1 && endIndex > -1) {
|
||||
errors.push(
|
||||
getParseError(
|
||||
`Got interpolation (${start}${end}) where expression was expected`,
|
||||
`Got interpolation ({{}}) where expression was expected`,
|
||||
input,
|
||||
`at column ${startIndex} in`,
|
||||
parseSourceSpan,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import * as html from '../ml_parser/ast';
|
||||
import {DEFAULT_CONTAINER_BLOCKS, InterpolationConfig} from '../ml_parser/defaults';
|
||||
import {DEFAULT_CONTAINER_BLOCKS} from '../ml_parser/defaults';
|
||||
import {ParseTreeResult} from '../ml_parser/parser';
|
||||
import {TokenType} from '../ml_parser/tokens';
|
||||
import {ParseError} from '../parse_util';
|
||||
|
|
@ -28,24 +28,22 @@ let i18nCommentsWarned = false;
|
|||
*/
|
||||
export function extractMessages(
|
||||
nodes: html.Node[],
|
||||
interpolationConfig: InterpolationConfig,
|
||||
implicitTags: string[],
|
||||
implicitAttrs: {[k: string]: string[]},
|
||||
preserveSignificantWhitespace: boolean,
|
||||
): ExtractionResult {
|
||||
const visitor = new _Visitor(implicitTags, implicitAttrs, preserveSignificantWhitespace);
|
||||
return visitor.extract(nodes, interpolationConfig);
|
||||
return visitor.extract(nodes);
|
||||
}
|
||||
|
||||
export function mergeTranslations(
|
||||
nodes: html.Node[],
|
||||
translations: TranslationBundle,
|
||||
interpolationConfig: InterpolationConfig,
|
||||
implicitTags: string[],
|
||||
implicitAttrs: {[k: string]: string[]},
|
||||
): ParseTreeResult {
|
||||
const visitor = new _Visitor(implicitTags, implicitAttrs);
|
||||
return visitor.merge(nodes, translations, interpolationConfig);
|
||||
return visitor.merge(nodes, translations);
|
||||
}
|
||||
|
||||
export class ExtractionResult {
|
||||
|
|
@ -106,8 +104,8 @@ class _Visitor implements html.Visitor {
|
|||
/**
|
||||
* Extracts the messages from the tree
|
||||
*/
|
||||
extract(nodes: html.Node[], interpolationConfig: InterpolationConfig): ExtractionResult {
|
||||
this._init(_VisitorMode.Extract, interpolationConfig);
|
||||
extract(nodes: html.Node[]): ExtractionResult {
|
||||
this._init(_VisitorMode.Extract);
|
||||
|
||||
nodes.forEach((node) => node.visit(this, null));
|
||||
|
||||
|
|
@ -121,12 +119,8 @@ class _Visitor implements html.Visitor {
|
|||
/**
|
||||
* Returns a tree where all translatable nodes are translated
|
||||
*/
|
||||
merge(
|
||||
nodes: html.Node[],
|
||||
translations: TranslationBundle,
|
||||
interpolationConfig: InterpolationConfig,
|
||||
): ParseTreeResult {
|
||||
this._init(_VisitorMode.Merge, interpolationConfig);
|
||||
merge(nodes: html.Node[], translations: TranslationBundle): ParseTreeResult {
|
||||
this._init(_VisitorMode.Merge);
|
||||
this._translations = translations;
|
||||
|
||||
// Construct a single fake root element
|
||||
|
|
@ -280,7 +274,7 @@ class _Visitor implements html.Visitor {
|
|||
throw new Error('unreachable code');
|
||||
}
|
||||
|
||||
private _init(mode: _VisitorMode, interpolationConfig: InterpolationConfig): void {
|
||||
private _init(mode: _VisitorMode): void {
|
||||
this._mode = mode;
|
||||
this._inI18nBlock = false;
|
||||
this._inI18nNode = false;
|
||||
|
|
@ -291,7 +285,6 @@ class _Visitor implements html.Visitor {
|
|||
this._messages = [];
|
||||
this._inImplicitNode = false;
|
||||
this._createI18nMessage = createI18nMessageFactory(
|
||||
interpolationConfig,
|
||||
DEFAULT_CONTAINER_BLOCKS,
|
||||
// When dropping significant whitespace we need to retain whitespace tokens or
|
||||
// else we won't be able to reuse source spans because empty tokens would be
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import {MissingTranslationStrategy} from '../core';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../ml_parser/defaults';
|
||||
import {HtmlParser} from '../ml_parser/html_parser';
|
||||
import {TokenizeOptions} from '../ml_parser/lexer';
|
||||
import {ParseTreeResult} from '../ml_parser/parser';
|
||||
|
|
@ -57,20 +56,13 @@ export class I18NHtmlParser implements HtmlParser {
|
|||
}
|
||||
|
||||
parse(source: string, url: string, options: TokenizeOptions = {}): ParseTreeResult {
|
||||
const interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
|
||||
const parseResult = this._htmlParser.parse(source, url, {interpolationConfig, ...options});
|
||||
const parseResult = this._htmlParser.parse(source, url, {...options});
|
||||
|
||||
if (parseResult.errors.length) {
|
||||
return new ParseTreeResult(parseResult.rootNodes, parseResult.errors);
|
||||
}
|
||||
|
||||
return mergeTranslations(
|
||||
parseResult.rootNodes,
|
||||
this._translationBundle,
|
||||
interpolationConfig,
|
||||
[],
|
||||
{},
|
||||
);
|
||||
return mergeTranslations(parseResult.rootNodes, this._translationBundle, [], {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {Lexer as ExpressionLexer} from '../expression_parser/lexer';
|
|||
import {Parser as ExpressionParser} from '../expression_parser/parser';
|
||||
import {serialize as serializeExpression} from '../expression_parser/serializer';
|
||||
import * as html from '../ml_parser/ast';
|
||||
import {InterpolationConfig} from '../ml_parser/defaults';
|
||||
import {getHtmlTagDefinition} from '../ml_parser/html_tags';
|
||||
import {
|
||||
AttributeValueInterpolationToken,
|
||||
|
|
@ -39,17 +38,15 @@ export interface I18nMessageFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a function converting html nodes to an i18n Message given an interpolationConfig
|
||||
* Returns a function converting html nodes to an i18n Message
|
||||
*/
|
||||
export function createI18nMessageFactory(
|
||||
interpolationConfig: InterpolationConfig,
|
||||
containerBlocks: Set<string>,
|
||||
retainEmptyTokens: boolean,
|
||||
preserveExpressionWhitespace: boolean,
|
||||
): I18nMessageFactory {
|
||||
const visitor = new _I18nVisitor(
|
||||
_expParser,
|
||||
interpolationConfig,
|
||||
containerBlocks,
|
||||
retainEmptyTokens,
|
||||
preserveExpressionWhitespace,
|
||||
|
|
@ -74,7 +71,6 @@ function noopVisitNodeFn(_html: html.Node, i18n: i18n.Node): i18n.Node {
|
|||
class _I18nVisitor implements html.Visitor {
|
||||
constructor(
|
||||
private _expressionParser: ExpressionParser,
|
||||
private _interpolationConfig: InterpolationConfig,
|
||||
private _containerBlocks: Set<string>,
|
||||
private readonly _retainEmptyTokens: boolean,
|
||||
private readonly _preserveExpressionWhitespace: boolean,
|
||||
|
|
@ -389,7 +385,6 @@ class _I18nVisitor implements html.Visitor {
|
|||
expression,
|
||||
/* location */ token.sourceSpan,
|
||||
/* absoluteOffset */ token.sourceSpan.start.offset,
|
||||
this._interpolationConfig,
|
||||
);
|
||||
return serializeExpression(expr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {InterpolationConfig} from '../ml_parser/defaults';
|
||||
import {HtmlParser} from '../ml_parser/html_parser';
|
||||
import {WhitespaceVisitor, visitAllWithSiblings} from '../ml_parser/html_whitespaces';
|
||||
import {ParseError} from '../parse_util';
|
||||
|
|
@ -29,15 +28,8 @@ export class MessageBundle {
|
|||
private readonly _preserveWhitespace = true,
|
||||
) {}
|
||||
|
||||
updateFromTemplate(
|
||||
source: string,
|
||||
url: string,
|
||||
interpolationConfig: InterpolationConfig,
|
||||
): ParseError[] {
|
||||
const htmlParserResult = this._htmlParser.parse(source, url, {
|
||||
tokenizeExpansionForms: true,
|
||||
interpolationConfig,
|
||||
});
|
||||
updateFromTemplate(source: string, url: string): ParseError[] {
|
||||
const htmlParserResult = this._htmlParser.parse(source, url, {tokenizeExpansionForms: true});
|
||||
|
||||
if (htmlParserResult.errors.length) {
|
||||
return htmlParserResult.errors;
|
||||
|
|
@ -55,7 +47,6 @@ export class MessageBundle {
|
|||
|
||||
const i18nParserResult = extractMessages(
|
||||
rootNodes,
|
||||
interpolationConfig,
|
||||
this._implicitTags,
|
||||
this._implicitAttrs,
|
||||
/* preserveSignificantWhitespace */ this._preserveWhitespace,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ import {
|
|||
ViewEncapsulation,
|
||||
} from './core';
|
||||
import {compileInjectable} from './injectable_compiler_2';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/defaults';
|
||||
import {
|
||||
DeclareVarStmt,
|
||||
Expression,
|
||||
|
|
@ -292,12 +291,11 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
|||
facade: R3ComponentMetadataFacade,
|
||||
): any {
|
||||
// Parse the template and check for errors.
|
||||
const {template, interpolation, defer} = parseJitTemplate(
|
||||
const {template, defer} = parseJitTemplate(
|
||||
facade.template,
|
||||
facade.name,
|
||||
sourceMapUrl,
|
||||
facade.preserveWhitespaces,
|
||||
facade.interpolation,
|
||||
undefined,
|
||||
);
|
||||
|
||||
|
|
@ -313,7 +311,6 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
|||
|
||||
styles: [...facade.styles, ...template.styles],
|
||||
encapsulation: facade.encapsulation,
|
||||
interpolation,
|
||||
changeDetection: facade.changeDetection ?? null,
|
||||
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
|
||||
viewProviders:
|
||||
|
|
@ -346,7 +343,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
|||
meta: R3ComponentMetadata<R3TemplateDependency>,
|
||||
): any {
|
||||
const constantPool = new ConstantPool();
|
||||
const bindingParser = makeBindingParser(meta.interpolation);
|
||||
const bindingParser = makeBindingParser();
|
||||
const res = compileComponentFromMetadata(meta, constantPool, bindingParser);
|
||||
return this.jitExpression(
|
||||
res.expression,
|
||||
|
|
@ -619,12 +616,11 @@ function convertDeclareComponentFacadeToMetadata(
|
|||
typeSourceSpan: ParseSourceSpan,
|
||||
sourceMapUrl: string,
|
||||
): R3ComponentMetadata<R3TemplateDependencyMetadata> {
|
||||
const {template, interpolation, defer} = parseJitTemplate(
|
||||
const {template, defer} = parseJitTemplate(
|
||||
decl.template,
|
||||
decl.type.name,
|
||||
sourceMapUrl,
|
||||
decl.preserveWhitespaces ?? false,
|
||||
decl.interpolation,
|
||||
decl.deferBlockDependencies,
|
||||
);
|
||||
|
||||
|
|
@ -673,7 +669,6 @@ function convertDeclareComponentFacadeToMetadata(
|
|||
defer,
|
||||
changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default,
|
||||
encapsulation: decl.encapsulation ?? ViewEncapsulation.Emulated,
|
||||
interpolation,
|
||||
declarationListEmitMode: DeclarationListEmitMode.ClosureResolved,
|
||||
relativeContextFilePath: '',
|
||||
i18nUseExternalIds: true,
|
||||
|
|
@ -737,17 +732,10 @@ function parseJitTemplate(
|
|||
typeName: string,
|
||||
sourceMapUrl: string,
|
||||
preserveWhitespaces: boolean,
|
||||
interpolation: [string, string] | undefined,
|
||||
deferBlockDependencies: (() => Promise<unknown> | null)[] | undefined,
|
||||
) {
|
||||
const interpolationConfig = interpolation
|
||||
? InterpolationConfig.fromArray(interpolation)
|
||||
: DEFAULT_INTERPOLATION_CONFIG;
|
||||
// Parse the template and check for errors.
|
||||
const parsed = parseTemplate(template, sourceMapUrl, {
|
||||
preserveWhitespaces,
|
||||
interpolationConfig,
|
||||
});
|
||||
const parsed = parseTemplate(template, sourceMapUrl, {preserveWhitespaces});
|
||||
if (parsed.errors !== null) {
|
||||
const errors = parsed.errors.map((err) => err.toString()).join(', ');
|
||||
throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
|
||||
|
|
@ -757,7 +745,6 @@ function parseJitTemplate(
|
|||
|
||||
return {
|
||||
template: parsed,
|
||||
interpolation: interpolationConfig,
|
||||
defer: createR3ComponentDeferMetadata(boundTarget, deferBlockDependencies),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ export class InterpolationConfig {
|
|||
) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* This symbol is referenced inside G3 and will require some cleanup.
|
||||
*/
|
||||
export const DEFAULT_INTERPOLATION_CONFIG: InterpolationConfig = new InterpolationConfig(
|
||||
'{{',
|
||||
'}}',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import * as chars from '../chars';
|
||||
import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from '../parse_util';
|
||||
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './defaults';
|
||||
import {NAMED_ENTITIES} from './entities';
|
||||
import {TagContentType, TagDefinition} from './tags';
|
||||
import {
|
||||
|
|
@ -42,8 +41,6 @@ export interface LexerRange {
|
|||
export interface TokenizeOptions {
|
||||
/** Whether to tokenize ICU messages (considered as text nodes when false). */
|
||||
tokenizeExpansionForms?: boolean;
|
||||
/** How to tokenize interpolation markers. */
|
||||
interpolationConfig?: InterpolationConfig;
|
||||
/**
|
||||
* The start and end point of the text to parse within the `source` string.
|
||||
* The entire `source` string is parsed if this is not provided.
|
||||
|
|
@ -158,11 +155,15 @@ const SUPPORTED_BLOCKS = [
|
|||
'@error',
|
||||
];
|
||||
|
||||
const INTERPOLATION = {
|
||||
start: '{{',
|
||||
end: '}}',
|
||||
};
|
||||
|
||||
// See https://www.w3.org/TR/html51/syntax.html#writing-html-documents
|
||||
class _Tokenizer {
|
||||
private _cursor: CharacterCursor;
|
||||
private _tokenizeIcu: boolean;
|
||||
private _interpolationConfig: InterpolationConfig;
|
||||
private _leadingTriviaCodePoints: number[] | undefined;
|
||||
private _currentTokenStart: CharacterCursor | null = null;
|
||||
private _currentTokenType: TokenType | null = null;
|
||||
|
|
@ -189,7 +190,6 @@ class _Tokenizer {
|
|||
options: TokenizeOptions,
|
||||
) {
|
||||
this._tokenizeIcu = options.tokenizeExpansionForms || false;
|
||||
this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
|
||||
this._leadingTriviaCodePoints =
|
||||
options.leadingTriviaChars && options.leadingTriviaChars.map((c) => c.codePointAt(0) || 0);
|
||||
const range = options.range || {
|
||||
|
|
@ -1145,7 +1145,7 @@ class _Tokenizer {
|
|||
|
||||
while (!endPredicate()) {
|
||||
const current = this._cursor.clone();
|
||||
if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
|
||||
if (this._attemptStr(INTERPOLATION.start)) {
|
||||
this._endToken([this._processCarriageReturns(parts.join(''))], current);
|
||||
parts.length = 0;
|
||||
this._consumeInterpolation(interpolationTokenType, current, endInterpolation);
|
||||
|
|
@ -1182,7 +1182,7 @@ class _Tokenizer {
|
|||
): void {
|
||||
const parts: string[] = [];
|
||||
this._beginToken(interpolationTokenType, interpolationStart);
|
||||
parts.push(this._interpolationConfig.start);
|
||||
parts.push(INTERPOLATION.start);
|
||||
|
||||
// Find the end of the interpolation, ignoring content inside quotes.
|
||||
const expressionStart = this._cursor.clone();
|
||||
|
|
@ -1205,10 +1205,10 @@ class _Tokenizer {
|
|||
}
|
||||
|
||||
if (inQuote === null) {
|
||||
if (this._attemptStr(this._interpolationConfig.end)) {
|
||||
if (this._attemptStr(INTERPOLATION.end)) {
|
||||
// We are not in a string, and we hit the end interpolation marker
|
||||
parts.push(this._getProcessedChars(expressionStart, current));
|
||||
parts.push(this._interpolationConfig.end);
|
||||
parts.push(INTERPOLATION.end);
|
||||
this._endToken(parts);
|
||||
return;
|
||||
} else if (this._attemptStr('//')) {
|
||||
|
|
@ -1380,13 +1380,10 @@ class _Tokenizer {
|
|||
if (this._cursor.peek() !== chars.$LBRACE) {
|
||||
return false;
|
||||
}
|
||||
if (this._interpolationConfig) {
|
||||
const start = this._cursor.clone();
|
||||
const isInterpolation = this._attemptStr(this._interpolationConfig.start);
|
||||
this._cursor = start;
|
||||
return !isInterpolation;
|
||||
}
|
||||
return true;
|
||||
const start = this._cursor.clone();
|
||||
const isInterpolation = this._attemptStr(INTERPOLATION.start);
|
||||
this._cursor = start;
|
||||
return !isInterpolation;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -228,11 +228,6 @@ export interface R3DeclareComponentMetadata extends R3DeclareDirectiveMetadata {
|
|||
*/
|
||||
encapsulation?: ViewEncapsulation;
|
||||
|
||||
/**
|
||||
* Overrides the default interpolation start and end delimiters. Defaults to {{ and }}.
|
||||
*/
|
||||
interpolation?: [string, string];
|
||||
|
||||
/**
|
||||
* Whether whitespace in the template should be preserved. Defaults to false.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
import * as core from '../../core';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../ml_parser/defaults';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../parse_util';
|
||||
import {RecursiveVisitor, visitAll} from '../r3_ast';
|
||||
|
|
@ -125,12 +124,6 @@ export function createComponentDefinitionMap(
|
|||
o.importExpr(R3.ViewEncapsulation).prop(core.ViewEncapsulation[meta.encapsulation]),
|
||||
);
|
||||
}
|
||||
if (meta.interpolation !== DEFAULT_INTERPOLATION_CONFIG) {
|
||||
definitionMap.set(
|
||||
'interpolation',
|
||||
o.literalArr([o.literal(meta.interpolation.start), o.literal(meta.interpolation.end)]),
|
||||
);
|
||||
}
|
||||
|
||||
if (template.preserveWhitespaces === true) {
|
||||
definitionMap.set('preserveWhitespaces', o.literal(true));
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, ViewEncapsulation} from '../../core';
|
||||
import {InterpolationConfig} from '../../ml_parser/defaults';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {ParseSourceSpan} from '../../parse_util';
|
||||
import * as t from '../r3_ast';
|
||||
|
|
@ -274,11 +273,6 @@ export interface R3ComponentMetadata<DeclarationT extends R3TemplateDependency>
|
|||
*/
|
||||
i18nUseExternalIds: boolean;
|
||||
|
||||
/**
|
||||
* Overrides the default interpolation start and end delimiters ({{ and }}).
|
||||
*/
|
||||
interpolation: InterpolationConfig;
|
||||
|
||||
/**
|
||||
* Strategy used for detecting changes in the component.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -11,11 +11,7 @@ import {computeDecimalDigest, computeDigest, decimalDigest} from '../../../i18n/
|
|||
import * as i18n from '../../../i18n/i18n_ast';
|
||||
import {createI18nMessageFactory, VisitNodeFn} from '../../../i18n/i18n_parser';
|
||||
import * as html from '../../../ml_parser/ast';
|
||||
import {
|
||||
DEFAULT_CONTAINER_BLOCKS,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
InterpolationConfig,
|
||||
} from '../../../ml_parser/defaults';
|
||||
import {DEFAULT_CONTAINER_BLOCKS} from '../../../ml_parser/defaults';
|
||||
import {ParseTreeResult} from '../../../ml_parser/parser';
|
||||
import * as o from '../../../output/output_ast';
|
||||
import {isTrustedTypesSink} from '../../../schema/trusted_types_sinks';
|
||||
|
|
@ -65,7 +61,6 @@ export class I18nMetaVisitor implements html.Visitor {
|
|||
private _errors: ParseError[] = [];
|
||||
|
||||
constructor(
|
||||
private interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
private keepI18nAttrs = false,
|
||||
private enableI18nLegacyMessageIdFormat = false,
|
||||
private containerBlocks: Set<string> = DEFAULT_CONTAINER_BLOCKS,
|
||||
|
|
@ -87,7 +82,6 @@ export class I18nMetaVisitor implements html.Visitor {
|
|||
): i18n.Message {
|
||||
const {meaning, description, customId} = this._parseMetadata(meta);
|
||||
const createI18nMessage = createI18nMessageFactory(
|
||||
this.interpolationConfig,
|
||||
this.containerBlocks,
|
||||
this.retainEmptyTokens,
|
||||
/* preserveExpressionWhitespace */ this.preserveSignificantWhitespace,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import {Lexer} from '../../expression_parser/lexer';
|
||||
import {Parser} from '../../expression_parser/parser';
|
||||
import * as html from '../../ml_parser/ast';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../ml_parser/defaults';
|
||||
import {HtmlParser} from '../../ml_parser/html_parser';
|
||||
import {WhitespaceVisitor} from '../../ml_parser/html_whitespaces';
|
||||
import {LexerRange} from '../../ml_parser/lexer';
|
||||
|
|
@ -39,10 +38,6 @@ export interface ParseTemplateOptions {
|
|||
* Preserve whitespace significant to rendering.
|
||||
*/
|
||||
preserveSignificantWhitespace?: boolean;
|
||||
/**
|
||||
* How to parse interpolation markers.
|
||||
*/
|
||||
interpolationConfig?: InterpolationConfig;
|
||||
/**
|
||||
* The start and end point of the text to parse within the `source` string.
|
||||
* The entire `source` string is parsed if this is not provided.
|
||||
|
|
@ -147,9 +142,9 @@ export function parseTemplate(
|
|||
templateUrl: string,
|
||||
options: ParseTemplateOptions = {},
|
||||
): ParsedTemplate {
|
||||
const {interpolationConfig, preserveWhitespaces, enableI18nLegacyMessageIdFormat} = options;
|
||||
const {preserveWhitespaces, enableI18nLegacyMessageIdFormat} = options;
|
||||
const selectorlessEnabled = options.enableSelectorless ?? false;
|
||||
const bindingParser = makeBindingParser(interpolationConfig, selectorlessEnabled);
|
||||
const bindingParser = makeBindingParser(selectorlessEnabled);
|
||||
const htmlParser = new HtmlParser();
|
||||
const parseResult = htmlParser.parse(template, templateUrl, {
|
||||
leadingTriviaChars: LEADING_TRIVIA_CHARS,
|
||||
|
|
@ -166,7 +161,6 @@ export function parseTemplate(
|
|||
parseResult.errors.length > 0
|
||||
) {
|
||||
const parsedTemplate: ParsedTemplate = {
|
||||
interpolationConfig,
|
||||
preserveWhitespaces,
|
||||
errors: parseResult.errors,
|
||||
nodes: [],
|
||||
|
|
@ -193,7 +187,6 @@ export function parseTemplate(
|
|||
// extraction process (ng extract-i18n) relies on a raw content to generate
|
||||
// message ids
|
||||
const i18nMetaVisitor = new I18nMetaVisitor(
|
||||
interpolationConfig,
|
||||
/* keepI18nAttrs */ !preserveWhitespaces,
|
||||
enableI18nLegacyMessageIdFormat,
|
||||
/* containerBlocks */ undefined,
|
||||
|
|
@ -208,7 +201,6 @@ export function parseTemplate(
|
|||
i18nMetaResult.errors.length > 0
|
||||
) {
|
||||
const parsedTemplate: ParsedTemplate = {
|
||||
interpolationConfig,
|
||||
preserveWhitespaces,
|
||||
errors: i18nMetaResult.errors,
|
||||
nodes: [],
|
||||
|
|
@ -252,7 +244,6 @@ export function parseTemplate(
|
|||
if (i18nMetaVisitor.hasI18nMeta) {
|
||||
rootNodes = html.visitAll(
|
||||
new I18nMetaVisitor(
|
||||
interpolationConfig,
|
||||
/* keepI18nAttrs */ false,
|
||||
/* enableI18nLegacyMessageIdFormat */ undefined,
|
||||
/* containerBlocks */ undefined,
|
||||
|
|
@ -272,7 +263,6 @@ export function parseTemplate(
|
|||
errors.push(...parseResult.errors, ...i18nMetaResult.errors);
|
||||
|
||||
const parsedTemplate: ParsedTemplate = {
|
||||
interpolationConfig,
|
||||
preserveWhitespaces,
|
||||
errors: errors.length > 0 ? errors : null,
|
||||
nodes,
|
||||
|
|
@ -292,16 +282,8 @@ const elementRegistry = new DomElementSchemaRegistry();
|
|||
/**
|
||||
* Construct a `BindingParser` with a default configuration.
|
||||
*/
|
||||
export function makeBindingParser(
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
selectorlessEnabled = false,
|
||||
): BindingParser {
|
||||
return new BindingParser(
|
||||
new Parser(new Lexer(), selectorlessEnabled),
|
||||
interpolationConfig,
|
||||
elementRegistry,
|
||||
[],
|
||||
);
|
||||
export function makeBindingParser(selectorlessEnabled = false): BindingParser {
|
||||
return new BindingParser(new Parser(new Lexer(), selectorlessEnabled), elementRegistry, []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -316,10 +298,6 @@ export interface ParsedTemplate {
|
|||
*/
|
||||
preserveWhitespaces?: boolean;
|
||||
|
||||
/**
|
||||
* How to parse interpolation markers.
|
||||
*/
|
||||
interpolationConfig?: InterpolationConfig;
|
||||
/**
|
||||
* Any errors from parsing the template the first time.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import {
|
|||
VariableBinding,
|
||||
} from '../expression_parser/ast';
|
||||
import {Parser} from '../expression_parser/parser';
|
||||
import {InterpolationConfig} from '../ml_parser/defaults';
|
||||
import {mergeNsAndName} from '../ml_parser/tags';
|
||||
import {InterpolatedAttributeToken, InterpolatedTextToken} from '../ml_parser/tokens';
|
||||
import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util';
|
||||
|
|
@ -62,15 +61,10 @@ export interface HostListeners {
|
|||
export class BindingParser {
|
||||
constructor(
|
||||
private _exprParser: Parser,
|
||||
private _interpolationConfig: InterpolationConfig,
|
||||
private _schemaRegistry: ElementSchemaRegistry,
|
||||
public errors: ParseError[],
|
||||
) {}
|
||||
|
||||
get interpolationConfig(): InterpolationConfig {
|
||||
return this._interpolationConfig;
|
||||
}
|
||||
|
||||
createBoundHostProperties(
|
||||
properties: HostProperties,
|
||||
sourceSpan: ParseSourceSpan,
|
||||
|
|
@ -154,7 +148,6 @@ export class BindingParser {
|
|||
sourceSpan,
|
||||
absoluteOffset,
|
||||
interpolatedTokens,
|
||||
this._interpolationConfig,
|
||||
)!;
|
||||
if (ast) {
|
||||
this.errors.push(...ast.errors);
|
||||
|
|
@ -536,18 +529,8 @@ export class BindingParser {
|
|||
): ASTWithSource {
|
||||
try {
|
||||
const ast = isHostBinding
|
||||
? this._exprParser.parseSimpleBinding(
|
||||
value,
|
||||
sourceSpan,
|
||||
absoluteOffset,
|
||||
this._interpolationConfig,
|
||||
)
|
||||
: this._exprParser.parseBinding(
|
||||
value,
|
||||
sourceSpan,
|
||||
absoluteOffset,
|
||||
this._interpolationConfig,
|
||||
);
|
||||
? this._exprParser.parseSimpleBinding(value, sourceSpan, absoluteOffset)
|
||||
: this._exprParser.parseBinding(value, sourceSpan, absoluteOffset);
|
||||
if (ast) {
|
||||
this.errors.push(...ast.errors);
|
||||
}
|
||||
|
|
@ -795,12 +778,7 @@ export class BindingParser {
|
|||
const absoluteOffset = sourceSpan && sourceSpan.start ? sourceSpan.start.offset : 0;
|
||||
|
||||
try {
|
||||
const ast = this._exprParser.parseAction(
|
||||
value,
|
||||
sourceSpan,
|
||||
absoluteOffset,
|
||||
this._interpolationConfig,
|
||||
);
|
||||
const ast = this._exprParser.parseAction(value, sourceSpan, absoluteOffset);
|
||||
if (ast) {
|
||||
this.errors.push(...ast.errors);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1316,17 +1316,6 @@ describe('parser', () => {
|
|||
checkInterpolation(`{{ 'foo' +\n 'bar' +\r 'baz' }}`, `{{ "foo" + "bar" + "baz" }}`);
|
||||
});
|
||||
|
||||
it('should support custom interpolation', () => {
|
||||
const parser = new Parser(new Lexer());
|
||||
const ast = parser.parseInterpolation('{% a %}', getFakeSpan(), 0, null, {
|
||||
start: '{%',
|
||||
end: '%}',
|
||||
})!.ast as any;
|
||||
expect(ast.strings).toEqual(['', '']);
|
||||
expect(ast.expressions.length).toEqual(1);
|
||||
expect(ast.expressions[0].name).toEqual('a');
|
||||
});
|
||||
|
||||
describe('comments', () => {
|
||||
it('should ignore comments in interpolation expressions', () => {
|
||||
checkInterpolation('{{a //comment}}', '{{ a }}');
|
||||
|
|
|
|||
|
|
@ -38,17 +38,14 @@ import {
|
|||
Unary,
|
||||
VoidExpression,
|
||||
} from '../../../src/expression_parser/ast';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../src/ml_parser/defaults';
|
||||
|
||||
class Unparser implements AstVisitor {
|
||||
private static _quoteRegExp = /"/g;
|
||||
// using non-null assertion because they're both re(set) by unparse()
|
||||
private _expression!: string;
|
||||
private _interpolationConfig!: InterpolationConfig;
|
||||
|
||||
unparse(ast: AST, interpolationConfig: InterpolationConfig) {
|
||||
unparse(ast: AST) {
|
||||
this._expression = '';
|
||||
this._interpolationConfig = interpolationConfig;
|
||||
this._visit(ast);
|
||||
return this._expression;
|
||||
}
|
||||
|
|
@ -128,9 +125,9 @@ class Unparser implements AstVisitor {
|
|||
for (let i = 0; i < ast.strings.length; i++) {
|
||||
this._expression += ast.strings[i];
|
||||
if (i < ast.expressions.length) {
|
||||
this._expression += `${this._interpolationConfig.start} `;
|
||||
this._expression += `{{ `;
|
||||
this._visit(ast.expressions[i]);
|
||||
this._expression += ` ${this._interpolationConfig.end}`;
|
||||
this._expression += ` }}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -249,20 +246,14 @@ class Unparser implements AstVisitor {
|
|||
|
||||
const sharedUnparser = new Unparser();
|
||||
|
||||
export function unparse(
|
||||
ast: AST,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): string {
|
||||
return sharedUnparser.unparse(ast, interpolationConfig);
|
||||
export function unparse(ast: AST): string {
|
||||
return sharedUnparser.unparse(ast);
|
||||
}
|
||||
|
||||
// [unparsed AST, original source code of AST]
|
||||
type UnparsedWithSpan = [string, string];
|
||||
|
||||
export function unparseWithSpan(
|
||||
ast: ASTWithSource,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): UnparsedWithSpan[] {
|
||||
export function unparseWithSpan(ast: ASTWithSource): UnparsedWithSpan[] {
|
||||
const unparsed: UnparsedWithSpan[] = [];
|
||||
const source = ast.source!;
|
||||
const recursiveSpanUnparser = new (class extends RecursiveAstVisitor {
|
||||
|
|
@ -270,7 +261,7 @@ export function unparseWithSpan(
|
|||
const span = ast[spanKey];
|
||||
const prefix = spanKey === 'span' ? '' : `[${spanKey}] `;
|
||||
const src = source.substring(span.start, span.end);
|
||||
unparsedList.push([unparse(ast, interpolationConfig), prefix + src]);
|
||||
unparsedList.push([unparse(ast), prefix + src]);
|
||||
}
|
||||
|
||||
override visit(ast: AST, unparsedList: UnparsedWithSpan[]) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, HtmlParser} from '../../index';
|
||||
import {HtmlParser} from '../../index';
|
||||
import {MissingTranslationStrategy} from '@angular/core';
|
||||
|
||||
import {digest, serializeNodes as serializeI18nNodes} from '../../src/i18n/digest';
|
||||
|
|
@ -530,7 +530,6 @@ describe('Merger', () => {
|
|||
const htmlNodes: html.Node[] = parseHtml(HTML);
|
||||
const messages: i18n.Message[] = extractMessages(
|
||||
htmlNodes,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
[],
|
||||
{},
|
||||
/* preserveSignificantWhitespace */ true,
|
||||
|
|
@ -541,13 +540,7 @@ describe('Merger', () => {
|
|||
i18nMsgMap[digest(messages[0])] = [];
|
||||
const translations = new TranslationBundle(i18nMsgMap, null, digest);
|
||||
|
||||
const output = mergeTranslations(
|
||||
htmlNodes,
|
||||
translations,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
[],
|
||||
{},
|
||||
);
|
||||
const output = mergeTranslations(htmlNodes, translations, [], {});
|
||||
expect(output.errors).toEqual([]);
|
||||
|
||||
expect(serializeHtmlNodes(output.rootNodes).join('')).toEqual(`<div></div>`);
|
||||
|
|
@ -607,7 +600,6 @@ describe('Merger', () => {
|
|||
const htmlNodes: html.Node[] = parseHtml(HTML);
|
||||
const messages: i18n.Message[] = extractMessages(
|
||||
htmlNodes,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
[],
|
||||
{},
|
||||
/* preserveSignificantWhitespace */ true,
|
||||
|
|
@ -618,13 +610,7 @@ describe('Merger', () => {
|
|||
i18nMsgMap[digest(messages[0])] = [];
|
||||
const translations = new TranslationBundle(i18nMsgMap, null, digest);
|
||||
|
||||
const output = mergeTranslations(
|
||||
htmlNodes,
|
||||
translations,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
[],
|
||||
{},
|
||||
);
|
||||
const output = mergeTranslations(htmlNodes, translations, [], {});
|
||||
expect(output.errors).toEqual([]);
|
||||
|
||||
expect(serializeHtmlNodes(output.rootNodes).join('')).toEqual(
|
||||
|
|
@ -675,7 +661,6 @@ function fakeTranslate(
|
|||
const htmlNodes: html.Node[] = parseHtml(content);
|
||||
const messages: i18n.Message[] = extractMessages(
|
||||
htmlNodes,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
/* preserveSignificantWhitespace */ true,
|
||||
|
|
@ -690,13 +675,7 @@ function fakeTranslate(
|
|||
});
|
||||
|
||||
const translationBundle = new TranslationBundle(i18nMsgMap, null, digest);
|
||||
const output = mergeTranslations(
|
||||
htmlNodes,
|
||||
translationBundle,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
);
|
||||
const output = mergeTranslations(htmlNodes, translationBundle, implicitTags, implicitAttrs);
|
||||
expect(output.errors).toEqual([]);
|
||||
|
||||
return serializeHtmlNodes(output.rootNodes).join('');
|
||||
|
|
@ -716,13 +695,7 @@ function fakeNoTranslate(
|
|||
MissingTranslationStrategy.Ignore,
|
||||
console,
|
||||
);
|
||||
const output = mergeTranslations(
|
||||
htmlNodes,
|
||||
translationBundle,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
);
|
||||
const output = mergeTranslations(htmlNodes, translationBundle, implicitTags, implicitAttrs);
|
||||
expect(output.errors).toEqual([]);
|
||||
|
||||
return serializeHtmlNodes(output.rootNodes).join('');
|
||||
|
|
@ -735,7 +708,6 @@ function extract(
|
|||
): [string[], string, string, string][] {
|
||||
const result = extractMessages(
|
||||
parseHtml(html),
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
/* preserveSignificantWhitespace */ true,
|
||||
|
|
@ -760,7 +732,6 @@ function extractErrors(
|
|||
): any[] {
|
||||
const errors = extractMessages(
|
||||
parseHtml(html),
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
/* preserveSignificantWhitespace */ true,
|
||||
|
|
|
|||
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
import {createI18nMessageFactory} from '../../src/i18n/i18n_parser';
|
||||
import {Node} from '../../src/ml_parser/ast';
|
||||
import {DEFAULT_CONTAINER_BLOCKS, DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/defaults';
|
||||
import {DEFAULT_CONTAINER_BLOCKS} from '../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
|
||||
describe('Message', () => {
|
||||
const messageFactory = createI18nMessageFactory(
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
DEFAULT_CONTAINER_BLOCKS,
|
||||
/* retainEmptyTokens */ false,
|
||||
/* preserveExpressionWhitespace */ true,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import {digest, serializeNodes} from '../../src/i18n/digest';
|
||||
import {extractMessages} from '../../src/i18n/extractor_merger';
|
||||
import {Message} from '../../src/i18n/i18n_ast';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
|
||||
describe('I18nParser', () => {
|
||||
|
|
@ -426,7 +425,6 @@ export function _extractMessages(
|
|||
|
||||
return extractMessages(
|
||||
parseResult.rootNodes,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
implicitTags,
|
||||
implicitAttrs,
|
||||
preserveSignificantWhitespace,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import {NgLocalization} from '@angular/common';
|
||||
import {Serializer} from '../../src/i18n';
|
||||
import {MessageBundle} from '../../src/i18n/message_bundle';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
import {ResourceLoader} from '../../src/resource_loader';
|
||||
import {Component, DebugElement, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
|
||||
|
|
@ -204,6 +203,6 @@ export function createComponent(html: string) {
|
|||
|
||||
export function serializeTranslations(html: string, serializer: Serializer) {
|
||||
const catalog = new MessageBundle(new HtmlParser(), [], {});
|
||||
catalog.updateFromTemplate(html, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
catalog.updateFromTemplate(html, 'file.ts');
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {serializeNodes} from '../../src/i18n/digest';
|
|||
import * as i18n from '../../src/i18n/i18n_ast';
|
||||
import {MessageBundle} from '../../src/i18n/message_bundle';
|
||||
import {Serializer} from '../../src/i18n/serializers/serializer';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
|
||||
describe('MessageBundle', () => {
|
||||
|
|
@ -22,11 +21,7 @@ describe('MessageBundle', () => {
|
|||
});
|
||||
|
||||
it('should extract the message to the catalog', () => {
|
||||
messages.updateFromTemplate(
|
||||
'<p i18n="m|d">Translate Me</p>',
|
||||
'url',
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
);
|
||||
messages.updateFromTemplate('<p i18n="m|d">Translate Me</p>', 'url');
|
||||
expect(humanizeMessages(messages)).toEqual(['Translate Me (m|d)']);
|
||||
});
|
||||
|
||||
|
|
@ -34,7 +29,6 @@ describe('MessageBundle', () => {
|
|||
messages.updateFromTemplate(
|
||||
'<p i18n="m|d@@1">Translate Me</p><p i18n="@@2">Translate Me</p><p i18n="@@2">Translate Me</p>',
|
||||
'url',
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
);
|
||||
expect(humanizeMessages(messages)).toEqual(['Translate Me (m|d)', 'Translate Me (|)']);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import {escapeRegExp} from '../../../src/util';
|
|||
import {serializeNodes} from '../../../src/i18n/digest';
|
||||
import {MessageBundle} from '../../../src/i18n/message_bundle';
|
||||
import {Xliff2} from '../../../src/i18n/serializers/xliff2';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../../src/ml_parser/html_parser';
|
||||
|
||||
const HTML = `
|
||||
|
|
@ -283,7 +282,7 @@ describe('XLIFF 2.0 serializer', () => {
|
|||
|
||||
function toXliff(html: string, locale: string | null = null): string {
|
||||
const catalog = new MessageBundle(new HtmlParser(), [], {}, locale);
|
||||
catalog.updateFromTemplate(html, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
catalog.updateFromTemplate(html, 'file.ts');
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import {escapeRegExp} from '../../../src/util';
|
|||
import {serializeNodes} from '../../../src/i18n/digest';
|
||||
import {MessageBundle} from '../../../src/i18n/message_bundle';
|
||||
import {Xliff} from '../../../src/i18n/serializers/xliff';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../../src/ml_parser/html_parser';
|
||||
|
||||
const HTML = `
|
||||
|
|
@ -261,7 +260,7 @@ describe('XLIFF serializer', () => {
|
|||
|
||||
function toXliff(html: string, locale: string | null = null): string {
|
||||
const catalog = new MessageBundle(new HtmlParser(), [], {}, locale);
|
||||
catalog.updateFromTemplate(html, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
catalog.updateFromTemplate(html, 'file.ts');
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import {MessageBundle} from '../../../src/i18n/message_bundle';
|
||||
import {Xmb} from '../../../src/i18n/serializers/xmb';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../../src/ml_parser/html_parser';
|
||||
|
||||
describe('XMB serializer', () => {
|
||||
|
|
@ -80,7 +79,7 @@ function toXmb(html: string, url: string, locale: string | null = null): string
|
|||
const catalog = new MessageBundle(new HtmlParser(), [], {}, locale);
|
||||
const serializer = new Xmb();
|
||||
|
||||
catalog.updateFromTemplate(html, url, DEFAULT_INTERPOLATION_CONFIG);
|
||||
catalog.updateFromTemplate(html, url);
|
||||
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import * as i18n from '../../src/i18n/i18n_ast';
|
||||
import {MessageBundle} from '../../src/i18n/message_bundle';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../src/ml_parser/html_parser';
|
||||
import {Xmb} from '../../src/i18n/serializers/xmb';
|
||||
|
||||
|
|
@ -452,7 +451,7 @@ function extractMessages(source: string, preserveWhitespace: boolean): Assertabl
|
|||
undefined /* locale */,
|
||||
preserveWhitespace,
|
||||
);
|
||||
const errors = bundle.updateFromTemplate(source, 'url', DEFAULT_INTERPOLATION_CONFIG);
|
||||
const errors = bundle.updateFromTemplate(source, 'url');
|
||||
if (errors.length !== 0) {
|
||||
throw new Error(
|
||||
`Failed to parse template:\n${errors.map((err) => err.toString()).join('\n\n')}`,
|
||||
|
|
|
|||
|
|
@ -2203,17 +2203,6 @@ describe('HtmlLexer', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should parse interpolation with custom markers', () => {
|
||||
expect(
|
||||
tokenizeAndHumanizeParts('{% a %}', {interpolationConfig: {start: '{%', end: '%}'}}),
|
||||
).toEqual([
|
||||
[TokenType.TEXT, ''],
|
||||
[TokenType.INTERPOLATION, '{%', ' a ', '%}'],
|
||||
[TokenType.TEXT, ''],
|
||||
[TokenType.EOF],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle CR & LF in text', () => {
|
||||
expect(tokenizeAndHumanizeParts('t\ne\rs\r\nt')).toEqual([
|
||||
[TokenType.TEXT, 't\ne\ns\nt'],
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import * as e from '../../../src/expression_parser/ast';
|
|||
import {Lexer} from '../../../src/expression_parser/lexer';
|
||||
import {Parser} from '../../../src/expression_parser/parser';
|
||||
import * as html from '../../../src/ml_parser/ast';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../src/ml_parser/defaults';
|
||||
import {HtmlParser} from '../../../src/ml_parser/html_parser';
|
||||
import {WhitespaceVisitor, visitAllWithSiblings} from '../../../src/ml_parser/html_whitespaces';
|
||||
import {ParseTreeResult} from '../../../src/ml_parser/parser';
|
||||
|
|
@ -182,12 +181,7 @@ export function parseR3(
|
|||
['onEvent'],
|
||||
['onEvent'],
|
||||
);
|
||||
const bindingParser = new BindingParser(
|
||||
expressionParser,
|
||||
DEFAULT_INTERPOLATION_CONFIG,
|
||||
schemaRegistry,
|
||||
[],
|
||||
);
|
||||
const bindingParser = new BindingParser(expressionParser, schemaRegistry, []);
|
||||
const r3Result = htmlAstToRender3Ast(htmlNodes, bindingParser, {collectCommentNodes: false});
|
||||
|
||||
if (r3Result.errors.length > 0 && !options.ignoreError) {
|
||||
|
|
@ -198,15 +192,9 @@ export function parseR3(
|
|||
return r3Result;
|
||||
}
|
||||
|
||||
export function processI18nMeta(
|
||||
htmlAstWithErrors: ParseTreeResult,
|
||||
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG,
|
||||
): ParseTreeResult {
|
||||
export function processI18nMeta(htmlAstWithErrors: ParseTreeResult): ParseTreeResult {
|
||||
return new ParseTreeResult(
|
||||
html.visitAll(
|
||||
new I18nMetaVisitor(interpolationConfig, /* keepI18nAttrs */ false),
|
||||
htmlAstWithErrors.rootNodes,
|
||||
),
|
||||
html.visitAll(new I18nMetaVisitor(/* keepI18nAttrs */ false), htmlAstWithErrors.rootNodes),
|
||||
htmlAstWithErrors.errors,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,12 @@
|
|||
|
||||
import ts from 'typescript';
|
||||
import {ReflectionHost, reflectObjectLiteral} from '@angular/compiler-cli/src/ngtsc/reflection';
|
||||
import {MigrationHost} from '../migration_host';
|
||||
import {getAngularDecorators, ResourceLoader} from '@angular/compiler-cli/src/ngtsc/annotations';
|
||||
import {PartialEvaluator} from '@angular/compiler-cli/src/ngtsc/partial_evaluator';
|
||||
import {
|
||||
ExternalTemplateDeclaration,
|
||||
InlineTemplateDeclaration,
|
||||
} from '@angular/compiler-cli/src/ngtsc/annotations/component/src/resources';
|
||||
import {DEFAULT_INTERPOLATION_CONFIG} from '@angular/compiler';
|
||||
|
||||
/**
|
||||
* Attempts to extract the `TemplateDefinition` for the given
|
||||
|
|
@ -59,7 +57,6 @@ export function attemptExtractTemplateDefinition(
|
|||
return {
|
||||
isInline: true,
|
||||
expression: templateProp,
|
||||
interpolationConfig: DEFAULT_INTERPOLATION_CONFIG,
|
||||
preserveWhitespaces: false,
|
||||
resolvedTemplateUrl: containingFile,
|
||||
templateUrl: containingFile,
|
||||
|
|
@ -74,7 +71,6 @@ export function attemptExtractTemplateDefinition(
|
|||
if (typeof templateUrl === 'string') {
|
||||
return {
|
||||
isInline: false,
|
||||
interpolationConfig: DEFAULT_INTERPOLATION_CONFIG,
|
||||
preserveWhitespaces: false,
|
||||
templateUrlExpression: templateUrlProp,
|
||||
templateUrl,
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
|
|||
styles: string[];
|
||||
encapsulation: ViewEncapsulation;
|
||||
viewProviders: Provider[] | null;
|
||||
interpolation?: [string, string];
|
||||
changeDetection?: ChangeDetectionStrategy;
|
||||
hasDirectiveDependencies: boolean;
|
||||
}
|
||||
|
|
@ -277,7 +276,6 @@ export interface R3DeclareComponentFacade extends R3DeclareDirectiveFacade {
|
|||
animations?: OpaqueValue;
|
||||
changeDetection?: ChangeDetectionStrategy;
|
||||
encapsulation?: ViewEncapsulation;
|
||||
interpolation?: [string, string];
|
||||
preserveWhitespaces?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue