@angular/compiler 20.0.0-next.4 → 20.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/compiler.mjs +1052 -341
- package/fesm2022/compiler.mjs.map +1 -1
- package/index.d.ts +102 -17
- package/package.json +2 -2
package/fesm2022/compiler.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v20.0.0-next.
|
|
2
|
+
* @license Angular v20.0.0-next.6
|
|
3
3
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -1320,14 +1320,13 @@ class TemplateLiteralElementExpr extends Expression {
|
|
|
1320
1320
|
constructor(text, sourceSpan, rawText) {
|
|
1321
1321
|
super(STRING_TYPE, sourceSpan);
|
|
1322
1322
|
this.text = text;
|
|
1323
|
-
// If `rawText` is not provided,
|
|
1324
|
-
// associated `sourceSpan`. If that is also not available, "fake" the raw
|
|
1325
|
-
// string instead by escaping the following control sequences:
|
|
1323
|
+
// If `rawText` is not provided, "fake" the raw string by escaping the following sequences:
|
|
1326
1324
|
// - "\" would otherwise indicate that the next character is a control character.
|
|
1327
1325
|
// - "`" and "${" are template string control sequences that would otherwise prematurely
|
|
1328
1326
|
// indicate the end of the template literal element.
|
|
1329
|
-
|
|
1330
|
-
|
|
1327
|
+
// Note that we can't rely on the `sourceSpan` here, because it may be incorrect (see
|
|
1328
|
+
// https://github.com/angular/angular/pull/60267#discussion_r1986402524).
|
|
1329
|
+
this.rawText = rawText ?? escapeForTemplateLiteral(escapeSlashes(text));
|
|
1331
1330
|
}
|
|
1332
1331
|
visitExpression(visitor, context) {
|
|
1333
1332
|
return visitor.visitTemplateLiteralElementExpr(this, context);
|
|
@@ -2943,7 +2942,7 @@ class Identifiers {
|
|
|
2943
2942
|
static pipeBind3 = { name: 'ɵɵpipeBind3', moduleName: CORE };
|
|
2944
2943
|
static pipeBind4 = { name: 'ɵɵpipeBind4', moduleName: CORE };
|
|
2945
2944
|
static pipeBindV = { name: 'ɵɵpipeBindV', moduleName: CORE };
|
|
2946
|
-
static
|
|
2945
|
+
static domProperty = { name: 'ɵɵdomProperty', moduleName: CORE };
|
|
2947
2946
|
static property = { name: 'ɵɵproperty', moduleName: CORE };
|
|
2948
2947
|
static propertyInterpolate = {
|
|
2949
2948
|
name: 'ɵɵpropertyInterpolate',
|
|
@@ -5069,17 +5068,19 @@ let Element$1 = class Element {
|
|
|
5069
5068
|
attributes;
|
|
5070
5069
|
inputs;
|
|
5071
5070
|
outputs;
|
|
5071
|
+
directives;
|
|
5072
5072
|
children;
|
|
5073
5073
|
references;
|
|
5074
5074
|
sourceSpan;
|
|
5075
5075
|
startSourceSpan;
|
|
5076
5076
|
endSourceSpan;
|
|
5077
5077
|
i18n;
|
|
5078
|
-
constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5078
|
+
constructor(name, attributes, inputs, outputs, directives, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5079
5079
|
this.name = name;
|
|
5080
5080
|
this.attributes = attributes;
|
|
5081
5081
|
this.inputs = inputs;
|
|
5082
5082
|
this.outputs = outputs;
|
|
5083
|
+
this.directives = directives;
|
|
5083
5084
|
this.children = children;
|
|
5084
5085
|
this.references = references;
|
|
5085
5086
|
this.sourceSpan = sourceSpan;
|
|
@@ -5378,11 +5379,70 @@ let LetDeclaration$1 = class LetDeclaration {
|
|
|
5378
5379
|
return visitor.visitLetDeclaration(this);
|
|
5379
5380
|
}
|
|
5380
5381
|
};
|
|
5382
|
+
let Component$1 = class Component {
|
|
5383
|
+
componentName;
|
|
5384
|
+
tagName;
|
|
5385
|
+
fullName;
|
|
5386
|
+
attributes;
|
|
5387
|
+
inputs;
|
|
5388
|
+
outputs;
|
|
5389
|
+
directives;
|
|
5390
|
+
children;
|
|
5391
|
+
references;
|
|
5392
|
+
sourceSpan;
|
|
5393
|
+
startSourceSpan;
|
|
5394
|
+
endSourceSpan;
|
|
5395
|
+
i18n;
|
|
5396
|
+
constructor(componentName, tagName, fullName, attributes, inputs, outputs, directives, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5397
|
+
this.componentName = componentName;
|
|
5398
|
+
this.tagName = tagName;
|
|
5399
|
+
this.fullName = fullName;
|
|
5400
|
+
this.attributes = attributes;
|
|
5401
|
+
this.inputs = inputs;
|
|
5402
|
+
this.outputs = outputs;
|
|
5403
|
+
this.directives = directives;
|
|
5404
|
+
this.children = children;
|
|
5405
|
+
this.references = references;
|
|
5406
|
+
this.sourceSpan = sourceSpan;
|
|
5407
|
+
this.startSourceSpan = startSourceSpan;
|
|
5408
|
+
this.endSourceSpan = endSourceSpan;
|
|
5409
|
+
this.i18n = i18n;
|
|
5410
|
+
}
|
|
5411
|
+
visit(visitor) {
|
|
5412
|
+
return visitor.visitComponent(this);
|
|
5413
|
+
}
|
|
5414
|
+
};
|
|
5415
|
+
let Directive$1 = class Directive {
|
|
5416
|
+
name;
|
|
5417
|
+
attributes;
|
|
5418
|
+
inputs;
|
|
5419
|
+
outputs;
|
|
5420
|
+
references;
|
|
5421
|
+
sourceSpan;
|
|
5422
|
+
startSourceSpan;
|
|
5423
|
+
endSourceSpan;
|
|
5424
|
+
i18n;
|
|
5425
|
+
constructor(name, attributes, inputs, outputs, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5426
|
+
this.name = name;
|
|
5427
|
+
this.attributes = attributes;
|
|
5428
|
+
this.inputs = inputs;
|
|
5429
|
+
this.outputs = outputs;
|
|
5430
|
+
this.references = references;
|
|
5431
|
+
this.sourceSpan = sourceSpan;
|
|
5432
|
+
this.startSourceSpan = startSourceSpan;
|
|
5433
|
+
this.endSourceSpan = endSourceSpan;
|
|
5434
|
+
this.i18n = i18n;
|
|
5435
|
+
}
|
|
5436
|
+
visit(visitor) {
|
|
5437
|
+
return visitor.visitDirective(this);
|
|
5438
|
+
}
|
|
5439
|
+
};
|
|
5381
5440
|
class Template {
|
|
5382
5441
|
tagName;
|
|
5383
5442
|
attributes;
|
|
5384
5443
|
inputs;
|
|
5385
5444
|
outputs;
|
|
5445
|
+
directives;
|
|
5386
5446
|
templateAttrs;
|
|
5387
5447
|
children;
|
|
5388
5448
|
references;
|
|
@@ -5396,11 +5456,12 @@ class Template {
|
|
|
5396
5456
|
// `null` is a special case for when there is a structural directive on an `ng-template` so
|
|
5397
5457
|
// the renderer can differentiate between the synthetic template and the one written in the
|
|
5398
5458
|
// file.
|
|
5399
|
-
tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5459
|
+
tagName, attributes, inputs, outputs, directives, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5400
5460
|
this.tagName = tagName;
|
|
5401
5461
|
this.attributes = attributes;
|
|
5402
5462
|
this.inputs = inputs;
|
|
5403
5463
|
this.outputs = outputs;
|
|
5464
|
+
this.directives = directives;
|
|
5404
5465
|
this.templateAttrs = templateAttrs;
|
|
5405
5466
|
this.children = children;
|
|
5406
5467
|
this.references = references;
|
|
@@ -5419,13 +5480,17 @@ class Content {
|
|
|
5419
5480
|
attributes;
|
|
5420
5481
|
children;
|
|
5421
5482
|
sourceSpan;
|
|
5483
|
+
startSourceSpan;
|
|
5484
|
+
endSourceSpan;
|
|
5422
5485
|
i18n;
|
|
5423
5486
|
name = 'ng-content';
|
|
5424
|
-
constructor(selector, attributes, children, sourceSpan, i18n) {
|
|
5487
|
+
constructor(selector, attributes, children, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
|
|
5425
5488
|
this.selector = selector;
|
|
5426
5489
|
this.attributes = attributes;
|
|
5427
5490
|
this.children = children;
|
|
5428
5491
|
this.sourceSpan = sourceSpan;
|
|
5492
|
+
this.startSourceSpan = startSourceSpan;
|
|
5493
|
+
this.endSourceSpan = endSourceSpan;
|
|
5429
5494
|
this.i18n = i18n;
|
|
5430
5495
|
}
|
|
5431
5496
|
visit(visitor) {
|
|
@@ -5508,6 +5573,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
|
|
|
5508
5573
|
visitAll$1(this, element.attributes);
|
|
5509
5574
|
visitAll$1(this, element.inputs);
|
|
5510
5575
|
visitAll$1(this, element.outputs);
|
|
5576
|
+
visitAll$1(this, element.directives);
|
|
5511
5577
|
visitAll$1(this, element.children);
|
|
5512
5578
|
visitAll$1(this, element.references);
|
|
5513
5579
|
}
|
|
@@ -5515,6 +5581,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
|
|
|
5515
5581
|
visitAll$1(this, template.attributes);
|
|
5516
5582
|
visitAll$1(this, template.inputs);
|
|
5517
5583
|
visitAll$1(this, template.outputs);
|
|
5584
|
+
visitAll$1(this, template.directives);
|
|
5518
5585
|
visitAll$1(this, template.children);
|
|
5519
5586
|
visitAll$1(this, template.references);
|
|
5520
5587
|
visitAll$1(this, template.variables);
|
|
@@ -5556,6 +5623,20 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
|
|
|
5556
5623
|
visitContent(content) {
|
|
5557
5624
|
visitAll$1(this, content.children);
|
|
5558
5625
|
}
|
|
5626
|
+
visitComponent(component) {
|
|
5627
|
+
visitAll$1(this, component.attributes);
|
|
5628
|
+
visitAll$1(this, component.inputs);
|
|
5629
|
+
visitAll$1(this, component.outputs);
|
|
5630
|
+
visitAll$1(this, component.directives);
|
|
5631
|
+
visitAll$1(this, component.children);
|
|
5632
|
+
visitAll$1(this, component.references);
|
|
5633
|
+
}
|
|
5634
|
+
visitDirective(directive) {
|
|
5635
|
+
visitAll$1(this, directive.attributes);
|
|
5636
|
+
visitAll$1(this, directive.inputs);
|
|
5637
|
+
visitAll$1(this, directive.outputs);
|
|
5638
|
+
visitAll$1(this, directive.references);
|
|
5639
|
+
}
|
|
5559
5640
|
visitVariable(variable) { }
|
|
5560
5641
|
visitReference(reference) { }
|
|
5561
5642
|
visitTextAttribute(attribute) { }
|
|
@@ -6182,8 +6263,8 @@ const I18N_ICU_VAR_PREFIX = 'VAR_';
|
|
|
6182
6263
|
function isI18nAttribute(name) {
|
|
6183
6264
|
return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
|
|
6184
6265
|
}
|
|
6185
|
-
function hasI18nAttrs(
|
|
6186
|
-
return
|
|
6266
|
+
function hasI18nAttrs(node) {
|
|
6267
|
+
return node.attrs.some((attr) => isI18nAttribute(attr.name));
|
|
6187
6268
|
}
|
|
6188
6269
|
function icuFromI18nMessage(message) {
|
|
6189
6270
|
return message.nodes[0];
|
|
@@ -8820,9 +8901,9 @@ var OpKind;
|
|
|
8820
8901
|
*/
|
|
8821
8902
|
OpKind[OpKind["I18nMessage"] = 31] = "I18nMessage";
|
|
8822
8903
|
/**
|
|
8823
|
-
* A
|
|
8904
|
+
* A binding to a native DOM property.
|
|
8824
8905
|
*/
|
|
8825
|
-
OpKind[OpKind["
|
|
8906
|
+
OpKind[OpKind["DomProperty"] = 32] = "DomProperty";
|
|
8826
8907
|
/**
|
|
8827
8908
|
* A namespace change, which causes the subsequent elements to be processed as either HTML or SVG.
|
|
8828
8909
|
*/
|
|
@@ -10329,7 +10410,7 @@ function transformExpressionsInOp(op, transform, flags) {
|
|
|
10329
10410
|
}
|
|
10330
10411
|
break;
|
|
10331
10412
|
case OpKind.Property:
|
|
10332
|
-
case OpKind.
|
|
10413
|
+
case OpKind.DomProperty:
|
|
10333
10414
|
case OpKind.Attribute:
|
|
10334
10415
|
if (op.expression instanceof Interpolation) {
|
|
10335
10416
|
transformExpressionsInInterpolation(op.expression, transform, flags);
|
|
@@ -11307,9 +11388,9 @@ function createSourceLocationOp(templatePath, locations) {
|
|
|
11307
11388
|
};
|
|
11308
11389
|
}
|
|
11309
11390
|
|
|
11310
|
-
function
|
|
11391
|
+
function createDomPropertyOp(name, expression, isAnimationTrigger, i18nContext, securityContext, sourceSpan) {
|
|
11311
11392
|
return {
|
|
11312
|
-
kind: OpKind.
|
|
11393
|
+
kind: OpKind.DomProperty,
|
|
11313
11394
|
name,
|
|
11314
11395
|
expression,
|
|
11315
11396
|
isAnimationTrigger,
|
|
@@ -11887,7 +11968,7 @@ function specializeBindings(job) {
|
|
|
11887
11968
|
case BindingKind.Property:
|
|
11888
11969
|
case BindingKind.Animation:
|
|
11889
11970
|
if (job.kind === CompilationJobKind.Host) {
|
|
11890
|
-
OpList.replace(op,
|
|
11971
|
+
OpList.replace(op, createDomPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.Animation, op.i18nContext, op.securityContext, op.sourceSpan));
|
|
11891
11972
|
}
|
|
11892
11973
|
else {
|
|
11893
11974
|
OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.Animation, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
|
|
@@ -11920,7 +12001,7 @@ const CHAIN_COMPATIBILITY = new Map([
|
|
|
11920
12001
|
[Identifiers.elementContainerStart, Identifiers.elementContainerStart],
|
|
11921
12002
|
[Identifiers.elementEnd, Identifiers.elementEnd],
|
|
11922
12003
|
[Identifiers.elementStart, Identifiers.elementStart],
|
|
11923
|
-
[Identifiers.
|
|
12004
|
+
[Identifiers.domProperty, Identifiers.domProperty],
|
|
11924
12005
|
[Identifiers.i18nExp, Identifiers.i18nExp],
|
|
11925
12006
|
[Identifiers.listener, Identifiers.listener],
|
|
11926
12007
|
[Identifiers.listener, Identifiers.listener],
|
|
@@ -13568,13 +13649,15 @@ class Attribute extends NodeWithI18n {
|
|
|
13568
13649
|
class Element extends NodeWithI18n {
|
|
13569
13650
|
name;
|
|
13570
13651
|
attrs;
|
|
13652
|
+
directives;
|
|
13571
13653
|
children;
|
|
13572
13654
|
startSourceSpan;
|
|
13573
13655
|
endSourceSpan;
|
|
13574
|
-
constructor(name, attrs, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
|
|
13656
|
+
constructor(name, attrs, directives, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
|
|
13575
13657
|
super(sourceSpan, i18n);
|
|
13576
13658
|
this.name = name;
|
|
13577
13659
|
this.attrs = attrs;
|
|
13660
|
+
this.directives = directives;
|
|
13578
13661
|
this.children = children;
|
|
13579
13662
|
this.startSourceSpan = startSourceSpan;
|
|
13580
13663
|
this.endSourceSpan = endSourceSpan;
|
|
@@ -13614,6 +13697,47 @@ class Block extends NodeWithI18n {
|
|
|
13614
13697
|
return visitor.visitBlock(this, context);
|
|
13615
13698
|
}
|
|
13616
13699
|
}
|
|
13700
|
+
class Component extends NodeWithI18n {
|
|
13701
|
+
componentName;
|
|
13702
|
+
tagName;
|
|
13703
|
+
fullName;
|
|
13704
|
+
attrs;
|
|
13705
|
+
directives;
|
|
13706
|
+
children;
|
|
13707
|
+
startSourceSpan;
|
|
13708
|
+
endSourceSpan;
|
|
13709
|
+
constructor(componentName, tagName, fullName, attrs, directives, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
|
|
13710
|
+
super(sourceSpan, i18n);
|
|
13711
|
+
this.componentName = componentName;
|
|
13712
|
+
this.tagName = tagName;
|
|
13713
|
+
this.fullName = fullName;
|
|
13714
|
+
this.attrs = attrs;
|
|
13715
|
+
this.directives = directives;
|
|
13716
|
+
this.children = children;
|
|
13717
|
+
this.startSourceSpan = startSourceSpan;
|
|
13718
|
+
this.endSourceSpan = endSourceSpan;
|
|
13719
|
+
}
|
|
13720
|
+
visit(visitor, context) {
|
|
13721
|
+
return visitor.visitComponent(this, context);
|
|
13722
|
+
}
|
|
13723
|
+
}
|
|
13724
|
+
class Directive {
|
|
13725
|
+
name;
|
|
13726
|
+
attrs;
|
|
13727
|
+
sourceSpan;
|
|
13728
|
+
startSourceSpan;
|
|
13729
|
+
endSourceSpan;
|
|
13730
|
+
constructor(name, attrs, sourceSpan, startSourceSpan, endSourceSpan = null) {
|
|
13731
|
+
this.name = name;
|
|
13732
|
+
this.attrs = attrs;
|
|
13733
|
+
this.sourceSpan = sourceSpan;
|
|
13734
|
+
this.startSourceSpan = startSourceSpan;
|
|
13735
|
+
this.endSourceSpan = endSourceSpan;
|
|
13736
|
+
}
|
|
13737
|
+
visit(visitor, context) {
|
|
13738
|
+
return visitor.visitDirective(this, context);
|
|
13739
|
+
}
|
|
13740
|
+
}
|
|
13617
13741
|
class BlockParameter {
|
|
13618
13742
|
expression;
|
|
13619
13743
|
sourceSpan;
|
|
@@ -13660,6 +13784,7 @@ class RecursiveVisitor {
|
|
|
13660
13784
|
visitElement(ast, context) {
|
|
13661
13785
|
this.visitChildren(context, (visit) => {
|
|
13662
13786
|
visit(ast.attrs);
|
|
13787
|
+
visit(ast.directives);
|
|
13663
13788
|
visit(ast.children);
|
|
13664
13789
|
});
|
|
13665
13790
|
}
|
|
@@ -13680,6 +13805,17 @@ class RecursiveVisitor {
|
|
|
13680
13805
|
}
|
|
13681
13806
|
visitBlockParameter(ast, context) { }
|
|
13682
13807
|
visitLetDeclaration(decl, context) { }
|
|
13808
|
+
visitComponent(component, context) {
|
|
13809
|
+
this.visitChildren(context, (visit) => {
|
|
13810
|
+
visit(component.attrs);
|
|
13811
|
+
visit(component.children);
|
|
13812
|
+
});
|
|
13813
|
+
}
|
|
13814
|
+
visitDirective(directive, context) {
|
|
13815
|
+
this.visitChildren(context, (visit) => {
|
|
13816
|
+
visit(directive.attrs);
|
|
13817
|
+
});
|
|
13818
|
+
}
|
|
13683
13819
|
visitChildren(context, cb) {
|
|
13684
13820
|
let results = [];
|
|
13685
13821
|
let t = this;
|
|
@@ -15883,11 +16019,13 @@ class _Tokenizer {
|
|
|
15883
16019
|
_currentTokenStart = null;
|
|
15884
16020
|
_currentTokenType = null;
|
|
15885
16021
|
_expansionCaseStack = [];
|
|
16022
|
+
_openDirectiveCount = 0;
|
|
15886
16023
|
_inInterpolation = false;
|
|
15887
16024
|
_preserveLineEndings;
|
|
15888
16025
|
_i18nNormalizeLineEndingsInICUs;
|
|
15889
16026
|
_tokenizeBlocks;
|
|
15890
16027
|
_tokenizeLet;
|
|
16028
|
+
_selectorlessEnabled;
|
|
15891
16029
|
tokens = [];
|
|
15892
16030
|
errors = [];
|
|
15893
16031
|
nonNormalizedIcuExpressions = [];
|
|
@@ -15915,6 +16053,7 @@ class _Tokenizer {
|
|
|
15915
16053
|
this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
|
|
15916
16054
|
this._tokenizeBlocks = options.tokenizeBlocks ?? true;
|
|
15917
16055
|
this._tokenizeLet = options.tokenizeLet ?? true;
|
|
16056
|
+
this._selectorlessEnabled = options.selectorlessEnabled ?? false;
|
|
15918
16057
|
try {
|
|
15919
16058
|
this._cursor.init();
|
|
15920
16059
|
}
|
|
@@ -15983,7 +16122,7 @@ class _Tokenizer {
|
|
|
15983
16122
|
this.handleError(e);
|
|
15984
16123
|
}
|
|
15985
16124
|
}
|
|
15986
|
-
this._beginToken(
|
|
16125
|
+
this._beginToken(41 /* TokenType.EOF */);
|
|
15987
16126
|
this._endToken([]);
|
|
15988
16127
|
}
|
|
15989
16128
|
_getBlockName() {
|
|
@@ -16326,7 +16465,7 @@ class _Tokenizer {
|
|
|
16326
16465
|
else {
|
|
16327
16466
|
const name = this._cursor.getChars(nameStart);
|
|
16328
16467
|
this._cursor.advance();
|
|
16329
|
-
const char = NAMED_ENTITIES[name];
|
|
16468
|
+
const char = NAMED_ENTITIES.hasOwnProperty(name) && NAMED_ENTITIES[name];
|
|
16330
16469
|
if (!char) {
|
|
16331
16470
|
throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
|
|
16332
16471
|
}
|
|
@@ -16382,7 +16521,7 @@ class _Tokenizer {
|
|
|
16382
16521
|
this._cursor.advance();
|
|
16383
16522
|
this._endToken([content]);
|
|
16384
16523
|
}
|
|
16385
|
-
_consumePrefixAndName() {
|
|
16524
|
+
_consumePrefixAndName(endPredicate) {
|
|
16386
16525
|
const nameOrPrefixStart = this._cursor.clone();
|
|
16387
16526
|
let prefix = '';
|
|
16388
16527
|
while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
|
|
@@ -16397,41 +16536,64 @@ class _Tokenizer {
|
|
|
16397
16536
|
else {
|
|
16398
16537
|
nameStart = nameOrPrefixStart;
|
|
16399
16538
|
}
|
|
16400
|
-
this._requireCharCodeUntilFn(
|
|
16539
|
+
this._requireCharCodeUntilFn(endPredicate, prefix === '' ? 0 : 1);
|
|
16401
16540
|
const name = this._cursor.getChars(nameStart);
|
|
16402
16541
|
return [prefix, name];
|
|
16403
16542
|
}
|
|
16404
16543
|
_consumeTagOpen(start) {
|
|
16405
16544
|
let tagName;
|
|
16406
16545
|
let prefix;
|
|
16407
|
-
let
|
|
16546
|
+
let closingTagName;
|
|
16547
|
+
let openToken;
|
|
16408
16548
|
try {
|
|
16409
|
-
if (
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16415
|
-
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
this._cursor.peek() !== $LT &&
|
|
16419
|
-
this._cursor.peek() !== $EOF) {
|
|
16420
|
-
this._consumeAttributeName();
|
|
16549
|
+
if (this._selectorlessEnabled && isSelectorlessNameStart(this._cursor.peek())) {
|
|
16550
|
+
openToken = this._consumeComponentOpenStart(start);
|
|
16551
|
+
[closingTagName, prefix, tagName] = openToken.parts;
|
|
16552
|
+
if (prefix) {
|
|
16553
|
+
closingTagName += `:${prefix}`;
|
|
16554
|
+
}
|
|
16555
|
+
if (tagName) {
|
|
16556
|
+
closingTagName += `:${tagName}`;
|
|
16557
|
+
}
|
|
16421
16558
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16559
|
+
}
|
|
16560
|
+
else {
|
|
16561
|
+
if (!isAsciiLetter(this._cursor.peek())) {
|
|
16562
|
+
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
|
|
16425
16563
|
}
|
|
16564
|
+
openToken = this._consumeTagOpenStart(start);
|
|
16565
|
+
prefix = openToken.parts[0];
|
|
16566
|
+
tagName = closingTagName = openToken.parts[1];
|
|
16426
16567
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16427
16568
|
}
|
|
16428
|
-
this.
|
|
16569
|
+
while (!isAttributeTerminator(this._cursor.peek())) {
|
|
16570
|
+
if (this._selectorlessEnabled && this._cursor.peek() === $AT) {
|
|
16571
|
+
const start = this._cursor.clone();
|
|
16572
|
+
const nameStart = start.clone();
|
|
16573
|
+
nameStart.advance();
|
|
16574
|
+
if (isSelectorlessNameStart(nameStart.peek())) {
|
|
16575
|
+
this._consumeDirective(start, nameStart);
|
|
16576
|
+
}
|
|
16577
|
+
}
|
|
16578
|
+
else {
|
|
16579
|
+
this._consumeAttribute();
|
|
16580
|
+
}
|
|
16581
|
+
}
|
|
16582
|
+
if (openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */) {
|
|
16583
|
+
this._consumeComponentOpenEnd();
|
|
16584
|
+
}
|
|
16585
|
+
else {
|
|
16586
|
+
this._consumeTagOpenEnd();
|
|
16587
|
+
}
|
|
16429
16588
|
}
|
|
16430
16589
|
catch (e) {
|
|
16431
16590
|
if (e instanceof _ControlFlowError) {
|
|
16432
|
-
if (
|
|
16591
|
+
if (openToken) {
|
|
16433
16592
|
// We errored before we could close the opening tag, so it is incomplete.
|
|
16434
|
-
|
|
16593
|
+
openToken.type =
|
|
16594
|
+
openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
|
|
16595
|
+
? 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */
|
|
16596
|
+
: 4 /* TokenType.INCOMPLETE_TAG_OPEN */;
|
|
16435
16597
|
}
|
|
16436
16598
|
else {
|
|
16437
16599
|
// When the start tag is invalid, assume we want a "<" as text.
|
|
@@ -16445,13 +16607,13 @@ class _Tokenizer {
|
|
|
16445
16607
|
}
|
|
16446
16608
|
const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
|
|
16447
16609
|
if (contentTokenType === TagContentType.RAW_TEXT) {
|
|
16448
|
-
this._consumeRawTextWithTagClose(
|
|
16610
|
+
this._consumeRawTextWithTagClose(openToken, closingTagName, false);
|
|
16449
16611
|
}
|
|
16450
16612
|
else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
|
|
16451
|
-
this._consumeRawTextWithTagClose(
|
|
16613
|
+
this._consumeRawTextWithTagClose(openToken, closingTagName, true);
|
|
16452
16614
|
}
|
|
16453
16615
|
}
|
|
16454
|
-
_consumeRawTextWithTagClose(
|
|
16616
|
+
_consumeRawTextWithTagClose(openToken, tagName, consumeEntities) {
|
|
16455
16617
|
this._consumeRawText(consumeEntities, () => {
|
|
16456
16618
|
if (!this._attemptCharCode($LT))
|
|
16457
16619
|
return false;
|
|
@@ -16463,23 +16625,79 @@ class _Tokenizer {
|
|
|
16463
16625
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16464
16626
|
return this._attemptCharCode($GT);
|
|
16465
16627
|
});
|
|
16466
|
-
this._beginToken(
|
|
16628
|
+
this._beginToken(openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
|
|
16629
|
+
? 36 /* TokenType.COMPONENT_CLOSE */
|
|
16630
|
+
: 3 /* TokenType.TAG_CLOSE */);
|
|
16467
16631
|
this._requireCharCodeUntilFn((code) => code === $GT, 3);
|
|
16468
16632
|
this._cursor.advance(); // Consume the `>`
|
|
16469
|
-
this._endToken(
|
|
16633
|
+
this._endToken(openToken.parts);
|
|
16470
16634
|
}
|
|
16471
16635
|
_consumeTagOpenStart(start) {
|
|
16472
16636
|
this._beginToken(0 /* TokenType.TAG_OPEN_START */, start);
|
|
16473
|
-
const parts = this._consumePrefixAndName();
|
|
16637
|
+
const parts = this._consumePrefixAndName(isNameEnd);
|
|
16474
16638
|
return this._endToken(parts);
|
|
16475
16639
|
}
|
|
16640
|
+
_consumeComponentOpenStart(start) {
|
|
16641
|
+
this._beginToken(33 /* TokenType.COMPONENT_OPEN_START */, start);
|
|
16642
|
+
const parts = this._consumeComponentName();
|
|
16643
|
+
return this._endToken(parts);
|
|
16644
|
+
}
|
|
16645
|
+
_consumeComponentName() {
|
|
16646
|
+
const nameStart = this._cursor.clone();
|
|
16647
|
+
while (isSelectorlessNameChar(this._cursor.peek())) {
|
|
16648
|
+
this._cursor.advance();
|
|
16649
|
+
}
|
|
16650
|
+
const name = this._cursor.getChars(nameStart);
|
|
16651
|
+
let prefix = '';
|
|
16652
|
+
let tagName = '';
|
|
16653
|
+
if (this._cursor.peek() === $COLON) {
|
|
16654
|
+
this._cursor.advance();
|
|
16655
|
+
[prefix, tagName] = this._consumePrefixAndName(isNameEnd);
|
|
16656
|
+
}
|
|
16657
|
+
return [name, prefix, tagName];
|
|
16658
|
+
}
|
|
16659
|
+
_consumeAttribute() {
|
|
16660
|
+
this._consumeAttributeName();
|
|
16661
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16662
|
+
if (this._attemptCharCode($EQ)) {
|
|
16663
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16664
|
+
this._consumeAttributeValue();
|
|
16665
|
+
}
|
|
16666
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16667
|
+
}
|
|
16476
16668
|
_consumeAttributeName() {
|
|
16477
16669
|
const attrNameStart = this._cursor.peek();
|
|
16478
16670
|
if (attrNameStart === $SQ || attrNameStart === $DQ) {
|
|
16479
16671
|
throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
|
|
16480
16672
|
}
|
|
16481
16673
|
this._beginToken(14 /* TokenType.ATTR_NAME */);
|
|
16482
|
-
|
|
16674
|
+
let nameEndPredicate;
|
|
16675
|
+
if (this._openDirectiveCount > 0) {
|
|
16676
|
+
// If we're parsing attributes inside of directive syntax, we have to terminate the name
|
|
16677
|
+
// on the first non-matching closing paren. For example, if we have `@Dir(someAttr)`,
|
|
16678
|
+
// `@Dir` and `(` will have already been captured as `DIRECTIVE_NAME` and `DIRECTIVE_OPEN`
|
|
16679
|
+
// respectively, but the `)` will get captured as a part of the name for `someAttr`
|
|
16680
|
+
// because normally that would be an event binding.
|
|
16681
|
+
let openParens = 0;
|
|
16682
|
+
nameEndPredicate = (code) => {
|
|
16683
|
+
if (this._openDirectiveCount > 0) {
|
|
16684
|
+
if (code === $LPAREN) {
|
|
16685
|
+
openParens++;
|
|
16686
|
+
}
|
|
16687
|
+
else if (code === $RPAREN) {
|
|
16688
|
+
if (openParens === 0) {
|
|
16689
|
+
return true;
|
|
16690
|
+
}
|
|
16691
|
+
openParens--;
|
|
16692
|
+
}
|
|
16693
|
+
}
|
|
16694
|
+
return isNameEnd(code);
|
|
16695
|
+
};
|
|
16696
|
+
}
|
|
16697
|
+
else {
|
|
16698
|
+
nameEndPredicate = isNameEnd;
|
|
16699
|
+
}
|
|
16700
|
+
const prefixAndName = this._consumePrefixAndName(nameEndPredicate);
|
|
16483
16701
|
this._endToken(prefixAndName);
|
|
16484
16702
|
}
|
|
16485
16703
|
_consumeAttributeValue() {
|
|
@@ -16510,10 +16728,32 @@ class _Tokenizer {
|
|
|
16510
16728
|
this._requireCharCode($GT);
|
|
16511
16729
|
this._endToken([]);
|
|
16512
16730
|
}
|
|
16731
|
+
_consumeComponentOpenEnd() {
|
|
16732
|
+
const tokenType = this._attemptCharCode($SLASH)
|
|
16733
|
+
? 35 /* TokenType.COMPONENT_OPEN_END_VOID */
|
|
16734
|
+
: 34 /* TokenType.COMPONENT_OPEN_END */;
|
|
16735
|
+
this._beginToken(tokenType);
|
|
16736
|
+
this._requireCharCode($GT);
|
|
16737
|
+
this._endToken([]);
|
|
16738
|
+
}
|
|
16513
16739
|
_consumeTagClose(start) {
|
|
16740
|
+
if (this._selectorlessEnabled) {
|
|
16741
|
+
const clone = start.clone();
|
|
16742
|
+
while (clone.peek() !== $GT && !isSelectorlessNameStart(clone.peek())) {
|
|
16743
|
+
clone.advance();
|
|
16744
|
+
}
|
|
16745
|
+
if (isSelectorlessNameStart(clone.peek())) {
|
|
16746
|
+
this._beginToken(36 /* TokenType.COMPONENT_CLOSE */, start);
|
|
16747
|
+
const parts = this._consumeComponentName();
|
|
16748
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16749
|
+
this._requireCharCode($GT);
|
|
16750
|
+
this._endToken(parts);
|
|
16751
|
+
return;
|
|
16752
|
+
}
|
|
16753
|
+
}
|
|
16514
16754
|
this._beginToken(3 /* TokenType.TAG_CLOSE */, start);
|
|
16515
16755
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16516
|
-
const prefixAndName = this._consumePrefixAndName();
|
|
16756
|
+
const prefixAndName = this._consumePrefixAndName(isNameEnd);
|
|
16517
16757
|
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16518
16758
|
this._requireCharCode($GT);
|
|
16519
16759
|
this._endToken(prefixAndName);
|
|
@@ -16669,6 +16909,50 @@ class _Tokenizer {
|
|
|
16669
16909
|
parts.push(this._getProcessedChars(expressionStart, this._cursor));
|
|
16670
16910
|
this._endToken(parts);
|
|
16671
16911
|
}
|
|
16912
|
+
_consumeDirective(start, nameStart) {
|
|
16913
|
+
this._requireCharCode($AT);
|
|
16914
|
+
// Skip over the @ since it's not part of the name.
|
|
16915
|
+
this._cursor.advance();
|
|
16916
|
+
// Capture the rest of the name.
|
|
16917
|
+
while (isSelectorlessNameChar(this._cursor.peek())) {
|
|
16918
|
+
this._cursor.advance();
|
|
16919
|
+
}
|
|
16920
|
+
// Capture the opening token.
|
|
16921
|
+
this._beginToken(38 /* TokenType.DIRECTIVE_NAME */, start);
|
|
16922
|
+
const name = this._cursor.getChars(nameStart);
|
|
16923
|
+
this._endToken([name]);
|
|
16924
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16925
|
+
// Optionally there might be attributes bound to the specific directive.
|
|
16926
|
+
// Stop parsing if there's no opening character for them.
|
|
16927
|
+
if (this._cursor.peek() !== $LPAREN) {
|
|
16928
|
+
return;
|
|
16929
|
+
}
|
|
16930
|
+
this._openDirectiveCount++;
|
|
16931
|
+
this._beginToken(39 /* TokenType.DIRECTIVE_OPEN */);
|
|
16932
|
+
this._cursor.advance();
|
|
16933
|
+
this._endToken([]);
|
|
16934
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16935
|
+
// Capture all the attributes until we hit a closing paren.
|
|
16936
|
+
while (!isAttributeTerminator(this._cursor.peek()) && this._cursor.peek() !== $RPAREN) {
|
|
16937
|
+
this._consumeAttribute();
|
|
16938
|
+
}
|
|
16939
|
+
// Trim any trailing whitespace.
|
|
16940
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16941
|
+
this._openDirectiveCount--;
|
|
16942
|
+
if (this._cursor.peek() !== $RPAREN) {
|
|
16943
|
+
// Stop parsing, instead of throwing, if we've hit the end of the tag.
|
|
16944
|
+
// This can be handled better later when turning the tokens into AST.
|
|
16945
|
+
if (this._cursor.peek() === $GT || this._cursor.peek() === $SLASH) {
|
|
16946
|
+
return;
|
|
16947
|
+
}
|
|
16948
|
+
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
|
|
16949
|
+
}
|
|
16950
|
+
// Capture the closing token.
|
|
16951
|
+
this._beginToken(40 /* TokenType.DIRECTIVE_CLOSE */);
|
|
16952
|
+
this._cursor.advance();
|
|
16953
|
+
this._endToken([]);
|
|
16954
|
+
this._attemptCharCodeUntilFn(isNotWhitespace);
|
|
16955
|
+
}
|
|
16672
16956
|
_getProcessedChars(start, end) {
|
|
16673
16957
|
return this._processCarriageReturns(end.getChars(start));
|
|
16674
16958
|
}
|
|
@@ -16784,6 +17068,15 @@ function isBlockNameChar(code) {
|
|
|
16784
17068
|
function isBlockParameterChar(code) {
|
|
16785
17069
|
return code !== $SEMICOLON && isNotWhitespace(code);
|
|
16786
17070
|
}
|
|
17071
|
+
function isSelectorlessNameStart(code) {
|
|
17072
|
+
return code === $_ || (code >= $A && code <= $Z);
|
|
17073
|
+
}
|
|
17074
|
+
function isSelectorlessNameChar(code) {
|
|
17075
|
+
return isAsciiLetter(code) || isDigit(code) || code === $_;
|
|
17076
|
+
}
|
|
17077
|
+
function isAttributeTerminator(code) {
|
|
17078
|
+
return code === $SLASH || code === $GT || code === $LT || code === $EOF;
|
|
17079
|
+
}
|
|
16787
17080
|
function mergeTextTokens(srcTokens) {
|
|
16788
17081
|
const dstTokens = [];
|
|
16789
17082
|
let lastDstToken = undefined;
|
|
@@ -17080,26 +17373,26 @@ let Parser$1 = class Parser {
|
|
|
17080
17373
|
};
|
|
17081
17374
|
class _TreeBuilder {
|
|
17082
17375
|
tokens;
|
|
17083
|
-
|
|
17376
|
+
tagDefinitionResolver;
|
|
17084
17377
|
_index = -1;
|
|
17085
17378
|
// `_peek` will be initialized by the call to `_advance()` in the constructor.
|
|
17086
17379
|
_peek;
|
|
17087
17380
|
_containerStack = [];
|
|
17088
17381
|
rootNodes = [];
|
|
17089
17382
|
errors = [];
|
|
17090
|
-
constructor(tokens,
|
|
17383
|
+
constructor(tokens, tagDefinitionResolver) {
|
|
17091
17384
|
this.tokens = tokens;
|
|
17092
|
-
this.
|
|
17385
|
+
this.tagDefinitionResolver = tagDefinitionResolver;
|
|
17093
17386
|
this._advance();
|
|
17094
17387
|
}
|
|
17095
17388
|
build() {
|
|
17096
|
-
while (this._peek.type !==
|
|
17389
|
+
while (this._peek.type !== 41 /* TokenType.EOF */) {
|
|
17097
17390
|
if (this._peek.type === 0 /* TokenType.TAG_OPEN_START */ ||
|
|
17098
17391
|
this._peek.type === 4 /* TokenType.INCOMPLETE_TAG_OPEN */) {
|
|
17099
|
-
this.
|
|
17392
|
+
this._consumeElementStartTag(this._advance());
|
|
17100
17393
|
}
|
|
17101
17394
|
else if (this._peek.type === 3 /* TokenType.TAG_CLOSE */) {
|
|
17102
|
-
this.
|
|
17395
|
+
this._consumeElementEndTag(this._advance());
|
|
17103
17396
|
}
|
|
17104
17397
|
else if (this._peek.type === 12 /* TokenType.CDATA_START */) {
|
|
17105
17398
|
this._closeVoidElement();
|
|
@@ -17138,6 +17431,13 @@ class _TreeBuilder {
|
|
|
17138
17431
|
this._closeVoidElement();
|
|
17139
17432
|
this._consumeIncompleteLet(this._advance());
|
|
17140
17433
|
}
|
|
17434
|
+
else if (this._peek.type === 33 /* TokenType.COMPONENT_OPEN_START */ ||
|
|
17435
|
+
this._peek.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */) {
|
|
17436
|
+
this._consumeComponentStartTag(this._advance());
|
|
17437
|
+
}
|
|
17438
|
+
else if (this._peek.type === 36 /* TokenType.COMPONENT_CLOSE */) {
|
|
17439
|
+
this._consumeComponentEndTag(this._advance());
|
|
17440
|
+
}
|
|
17141
17441
|
else {
|
|
17142
17442
|
// Skip all other tokens...
|
|
17143
17443
|
this._advance();
|
|
@@ -17211,9 +17511,9 @@ class _TreeBuilder {
|
|
|
17211
17511
|
if (!exp)
|
|
17212
17512
|
return null;
|
|
17213
17513
|
const end = this._advance();
|
|
17214
|
-
exp.push({ type:
|
|
17514
|
+
exp.push({ type: 41 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
|
|
17215
17515
|
// parse everything in between { and }
|
|
17216
|
-
const expansionCaseParser = new _TreeBuilder(exp, this.
|
|
17516
|
+
const expansionCaseParser = new _TreeBuilder(exp, this.tagDefinitionResolver);
|
|
17217
17517
|
expansionCaseParser.build();
|
|
17218
17518
|
if (expansionCaseParser.errors.length > 0) {
|
|
17219
17519
|
this.errors = this.errors.concat(expansionCaseParser.errors);
|
|
@@ -17251,7 +17551,7 @@ class _TreeBuilder {
|
|
|
17251
17551
|
return null;
|
|
17252
17552
|
}
|
|
17253
17553
|
}
|
|
17254
|
-
if (this._peek.type ===
|
|
17554
|
+
if (this._peek.type === 41 /* TokenType.EOF */) {
|
|
17255
17555
|
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
|
|
17256
17556
|
return null;
|
|
17257
17557
|
}
|
|
@@ -17266,7 +17566,7 @@ class _TreeBuilder {
|
|
|
17266
17566
|
const parent = this._getContainer();
|
|
17267
17567
|
if (parent != null &&
|
|
17268
17568
|
parent.children.length === 0 &&
|
|
17269
|
-
this.
|
|
17569
|
+
this._getTagDefinition(parent)?.ignoreFirstLf) {
|
|
17270
17570
|
text = text.substring(1);
|
|
17271
17571
|
tokens[0] = { type: token.type, sourceSpan: token.sourceSpan, parts: [text] };
|
|
17272
17572
|
}
|
|
@@ -17297,25 +17597,23 @@ class _TreeBuilder {
|
|
|
17297
17597
|
}
|
|
17298
17598
|
_closeVoidElement() {
|
|
17299
17599
|
const el = this._getContainer();
|
|
17300
|
-
if (el
|
|
17600
|
+
if (el !== null && this._getTagDefinition(el)?.isVoid) {
|
|
17301
17601
|
this._containerStack.pop();
|
|
17302
17602
|
}
|
|
17303
17603
|
}
|
|
17304
|
-
|
|
17305
|
-
const [prefix, name] = startTagToken.parts;
|
|
17604
|
+
_consumeElementStartTag(startTagToken) {
|
|
17306
17605
|
const attrs = [];
|
|
17307
|
-
|
|
17308
|
-
|
|
17309
|
-
|
|
17310
|
-
const fullName = this._getElementFullName(prefix, name, this._getClosestParentElement());
|
|
17606
|
+
const directives = [];
|
|
17607
|
+
this._consumeAttributesAndDirectives(attrs, directives);
|
|
17608
|
+
const fullName = this._getElementFullName(startTagToken, this._getClosestElementLikeParent());
|
|
17311
17609
|
let selfClosing = false;
|
|
17312
17610
|
// Note: There could have been a tokenizer error
|
|
17313
17611
|
// so that we don't get a token for the end tag...
|
|
17314
17612
|
if (this._peek.type === 2 /* TokenType.TAG_OPEN_END_VOID */) {
|
|
17315
17613
|
this._advance();
|
|
17316
17614
|
selfClosing = true;
|
|
17317
|
-
const tagDef = this.
|
|
17318
|
-
if (!(tagDef
|
|
17615
|
+
const tagDef = this._getTagDefinition(fullName);
|
|
17616
|
+
if (!(tagDef?.canSelfClose || getNsPrefix(fullName) !== null || tagDef?.isVoid)) {
|
|
17319
17617
|
this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void, custom and foreign elements can be self closed "${startTagToken.parts[1]}"`));
|
|
17320
17618
|
}
|
|
17321
17619
|
}
|
|
@@ -17327,10 +17625,10 @@ class _TreeBuilder {
|
|
|
17327
17625
|
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
17328
17626
|
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
|
|
17329
17627
|
const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
|
|
17330
|
-
const el = new Element(fullName, attrs, [], span, startSpan, undefined);
|
|
17331
|
-
const
|
|
17332
|
-
|
|
17333
|
-
|
|
17628
|
+
const el = new Element(fullName, attrs, directives, [], span, startSpan, undefined);
|
|
17629
|
+
const parent = this._getContainer();
|
|
17630
|
+
const isClosedByChild = parent !== null && !!this._getTagDefinition(parent)?.isClosedByChild(el.name);
|
|
17631
|
+
this._pushContainer(el, isClosedByChild);
|
|
17334
17632
|
if (selfClosing) {
|
|
17335
17633
|
// Elements that are self-closed have their `endSourceSpan` set to the full span, as the
|
|
17336
17634
|
// element start tag also represents the end tag.
|
|
@@ -17343,6 +17641,73 @@ class _TreeBuilder {
|
|
|
17343
17641
|
this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
|
|
17344
17642
|
}
|
|
17345
17643
|
}
|
|
17644
|
+
_consumeComponentStartTag(startToken) {
|
|
17645
|
+
const componentName = startToken.parts[0];
|
|
17646
|
+
const attrs = [];
|
|
17647
|
+
const directives = [];
|
|
17648
|
+
this._consumeAttributesAndDirectives(attrs, directives);
|
|
17649
|
+
const closestElement = this._getClosestElementLikeParent();
|
|
17650
|
+
const tagName = this._getComponentTagName(startToken, closestElement);
|
|
17651
|
+
const fullName = this._getComponentFullName(startToken, closestElement);
|
|
17652
|
+
const selfClosing = this._peek.type === 35 /* TokenType.COMPONENT_OPEN_END_VOID */;
|
|
17653
|
+
this._advance();
|
|
17654
|
+
const end = this._peek.sourceSpan.fullStart;
|
|
17655
|
+
const span = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
|
|
17656
|
+
const startSpan = new ParseSourceSpan(startToken.sourceSpan.start, end, startToken.sourceSpan.fullStart);
|
|
17657
|
+
const node = new Component(componentName, tagName, fullName, attrs, directives, [], span, startSpan, undefined);
|
|
17658
|
+
const parent = this._getContainer();
|
|
17659
|
+
const isClosedByChild = parent !== null &&
|
|
17660
|
+
node.tagName !== null &&
|
|
17661
|
+
!!this._getTagDefinition(parent)?.isClosedByChild(node.tagName);
|
|
17662
|
+
this._pushContainer(node, isClosedByChild);
|
|
17663
|
+
if (selfClosing) {
|
|
17664
|
+
this._popContainer(fullName, Component, span);
|
|
17665
|
+
}
|
|
17666
|
+
else if (startToken.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */) {
|
|
17667
|
+
this._popContainer(fullName, Component, null);
|
|
17668
|
+
this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
|
|
17669
|
+
}
|
|
17670
|
+
}
|
|
17671
|
+
_consumeAttributesAndDirectives(attributesResult, directivesResult) {
|
|
17672
|
+
while (this._peek.type === 14 /* TokenType.ATTR_NAME */ ||
|
|
17673
|
+
this._peek.type === 38 /* TokenType.DIRECTIVE_NAME */) {
|
|
17674
|
+
if (this._peek.type === 38 /* TokenType.DIRECTIVE_NAME */) {
|
|
17675
|
+
directivesResult.push(this._consumeDirective(this._peek));
|
|
17676
|
+
}
|
|
17677
|
+
else {
|
|
17678
|
+
attributesResult.push(this._consumeAttr(this._advance()));
|
|
17679
|
+
}
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
_consumeComponentEndTag(endToken) {
|
|
17683
|
+
const fullName = this._getComponentFullName(endToken, this._getClosestElementLikeParent());
|
|
17684
|
+
if (!this._popContainer(fullName, Component, endToken.sourceSpan)) {
|
|
17685
|
+
const container = this._containerStack[this._containerStack.length - 1];
|
|
17686
|
+
let suffix;
|
|
17687
|
+
if (container instanceof Component && container.componentName === endToken.parts[0]) {
|
|
17688
|
+
suffix = `, did you mean "${container.fullName}"?`;
|
|
17689
|
+
}
|
|
17690
|
+
else {
|
|
17691
|
+
suffix = '. It may happen when the tag has already been closed by another tag.';
|
|
17692
|
+
}
|
|
17693
|
+
const errMsg = `Unexpected closing tag "${fullName}"${suffix}`;
|
|
17694
|
+
this.errors.push(TreeError.create(fullName, endToken.sourceSpan, errMsg));
|
|
17695
|
+
}
|
|
17696
|
+
}
|
|
17697
|
+
_getTagDefinition(nodeOrName) {
|
|
17698
|
+
if (typeof nodeOrName === 'string') {
|
|
17699
|
+
return this.tagDefinitionResolver(nodeOrName);
|
|
17700
|
+
}
|
|
17701
|
+
else if (nodeOrName instanceof Element) {
|
|
17702
|
+
return this.tagDefinitionResolver(nodeOrName.name);
|
|
17703
|
+
}
|
|
17704
|
+
else if (nodeOrName instanceof Component && nodeOrName.tagName !== null) {
|
|
17705
|
+
return this.tagDefinitionResolver(nodeOrName.tagName);
|
|
17706
|
+
}
|
|
17707
|
+
else {
|
|
17708
|
+
return null;
|
|
17709
|
+
}
|
|
17710
|
+
}
|
|
17346
17711
|
_pushContainer(node, isClosedByChild) {
|
|
17347
17712
|
if (isClosedByChild) {
|
|
17348
17713
|
this._containerStack.pop();
|
|
@@ -17350,9 +17715,9 @@ class _TreeBuilder {
|
|
|
17350
17715
|
this._addToParent(node);
|
|
17351
17716
|
this._containerStack.push(node);
|
|
17352
17717
|
}
|
|
17353
|
-
|
|
17354
|
-
const fullName = this._getElementFullName(endTagToken
|
|
17355
|
-
if (this.
|
|
17718
|
+
_consumeElementEndTag(endTagToken) {
|
|
17719
|
+
const fullName = this._getElementFullName(endTagToken, this._getClosestElementLikeParent());
|
|
17720
|
+
if (this._getTagDefinition(fullName)?.isVoid) {
|
|
17356
17721
|
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
|
|
17357
17722
|
}
|
|
17358
17723
|
else if (!this._popContainer(fullName, Element, endTagToken.sourceSpan)) {
|
|
@@ -17370,7 +17735,8 @@ class _TreeBuilder {
|
|
|
17370
17735
|
let unexpectedCloseTagDetected = false;
|
|
17371
17736
|
for (let stackIndex = this._containerStack.length - 1; stackIndex >= 0; stackIndex--) {
|
|
17372
17737
|
const node = this._containerStack[stackIndex];
|
|
17373
|
-
|
|
17738
|
+
const nodeName = node instanceof Component ? node.fullName : node.name;
|
|
17739
|
+
if ((nodeName === expectedName || expectedName === null) && node instanceof expectedType) {
|
|
17374
17740
|
// Record the parse span with the element that is being closed. Any elements that are
|
|
17375
17741
|
// removed from the element stack at this point are closed implicitly, so they won't get
|
|
17376
17742
|
// an end source span (as there is no explicit closing element).
|
|
@@ -17380,8 +17746,7 @@ class _TreeBuilder {
|
|
|
17380
17746
|
return !unexpectedCloseTagDetected;
|
|
17381
17747
|
}
|
|
17382
17748
|
// Blocks and most elements are not self closing.
|
|
17383
|
-
if (node instanceof Block ||
|
|
17384
|
-
(node instanceof Element && !this.getTagDefinition(node.name).closedByParent)) {
|
|
17749
|
+
if (node instanceof Block || !this._getTagDefinition(node)?.closedByParent) {
|
|
17385
17750
|
// Note that we encountered an unexpected close tag but continue processing the element
|
|
17386
17751
|
// stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
|
|
17387
17752
|
// end tag in the stack.
|
|
@@ -17441,6 +17806,31 @@ class _TreeBuilder {
|
|
|
17441
17806
|
new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
|
|
17442
17807
|
return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
|
|
17443
17808
|
}
|
|
17809
|
+
_consumeDirective(nameToken) {
|
|
17810
|
+
const attributes = [];
|
|
17811
|
+
let startSourceSpanEnd = nameToken.sourceSpan.end;
|
|
17812
|
+
let endSourceSpan = null;
|
|
17813
|
+
this._advance();
|
|
17814
|
+
if (this._peek.type === 39 /* TokenType.DIRECTIVE_OPEN */) {
|
|
17815
|
+
// Capture the opening token in the start span.
|
|
17816
|
+
startSourceSpanEnd = this._peek.sourceSpan.end;
|
|
17817
|
+
this._advance();
|
|
17818
|
+
// Cast here is necessary, because TS doesn't know that `_advance` changed `_peek`.
|
|
17819
|
+
while (this._peek.type === 14 /* TokenType.ATTR_NAME */) {
|
|
17820
|
+
attributes.push(this._consumeAttr(this._advance()));
|
|
17821
|
+
}
|
|
17822
|
+
if (this._peek.type === 40 /* TokenType.DIRECTIVE_CLOSE */) {
|
|
17823
|
+
endSourceSpan = this._peek.sourceSpan;
|
|
17824
|
+
this._advance();
|
|
17825
|
+
}
|
|
17826
|
+
else {
|
|
17827
|
+
this.errors.push(TreeError.create(null, nameToken.sourceSpan, 'Unterminated directive definition'));
|
|
17828
|
+
}
|
|
17829
|
+
}
|
|
17830
|
+
const startSourceSpan = new ParseSourceSpan(nameToken.sourceSpan.start, startSourceSpanEnd, nameToken.sourceSpan.fullStart);
|
|
17831
|
+
const sourceSpan = new ParseSourceSpan(startSourceSpan.start, endSourceSpan === null ? nameToken.sourceSpan.end : endSourceSpan.end, startSourceSpan.fullStart);
|
|
17832
|
+
return new Directive(nameToken.parts[0], attributes, sourceSpan, startSourceSpan, endSourceSpan);
|
|
17833
|
+
}
|
|
17444
17834
|
_consumeBlockOpen(token) {
|
|
17445
17835
|
const parameters = [];
|
|
17446
17836
|
while (this._peek.type === 27 /* TokenType.BLOCK_PARAMETER */) {
|
|
@@ -17531,10 +17921,11 @@ class _TreeBuilder {
|
|
|
17531
17921
|
? this._containerStack[this._containerStack.length - 1]
|
|
17532
17922
|
: null;
|
|
17533
17923
|
}
|
|
17534
|
-
|
|
17924
|
+
_getClosestElementLikeParent() {
|
|
17535
17925
|
for (let i = this._containerStack.length - 1; i > -1; i--) {
|
|
17536
|
-
|
|
17537
|
-
|
|
17926
|
+
const current = this._containerStack[i];
|
|
17927
|
+
if (current instanceof Element || current instanceof Component) {
|
|
17928
|
+
return current;
|
|
17538
17929
|
}
|
|
17539
17930
|
}
|
|
17540
17931
|
return null;
|
|
@@ -17548,18 +17939,57 @@ class _TreeBuilder {
|
|
|
17548
17939
|
parent.children.push(node);
|
|
17549
17940
|
}
|
|
17550
17941
|
}
|
|
17551
|
-
_getElementFullName(
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17942
|
+
_getElementFullName(token, parent) {
|
|
17943
|
+
const prefix = this._getPrefix(token, parent);
|
|
17944
|
+
return mergeNsAndName(prefix, token.parts[1]);
|
|
17945
|
+
}
|
|
17946
|
+
_getComponentFullName(token, parent) {
|
|
17947
|
+
const componentName = token.parts[0];
|
|
17948
|
+
const tagName = this._getComponentTagName(token, parent);
|
|
17949
|
+
if (tagName === null) {
|
|
17950
|
+
return componentName;
|
|
17951
|
+
}
|
|
17952
|
+
return tagName.startsWith(':') ? componentName + tagName : `${componentName}:${tagName}`;
|
|
17953
|
+
}
|
|
17954
|
+
_getComponentTagName(token, parent) {
|
|
17955
|
+
const prefix = this._getPrefix(token, parent);
|
|
17956
|
+
const tagName = token.parts[2];
|
|
17957
|
+
if (!prefix && !tagName) {
|
|
17958
|
+
return null;
|
|
17959
|
+
}
|
|
17960
|
+
else if (!prefix && tagName) {
|
|
17961
|
+
return tagName;
|
|
17962
|
+
}
|
|
17963
|
+
else {
|
|
17964
|
+
// TODO(crisbeto): re-evaluate this fallback. Maybe base it off the class name?
|
|
17965
|
+
return mergeNsAndName(prefix, tagName || 'ng-component');
|
|
17966
|
+
}
|
|
17967
|
+
}
|
|
17968
|
+
_getPrefix(token, parent) {
|
|
17969
|
+
let prefix;
|
|
17970
|
+
let tagName;
|
|
17971
|
+
if (token.type === 33 /* TokenType.COMPONENT_OPEN_START */ ||
|
|
17972
|
+
token.type === 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */ ||
|
|
17973
|
+
token.type === 36 /* TokenType.COMPONENT_CLOSE */) {
|
|
17974
|
+
prefix = token.parts[1];
|
|
17975
|
+
tagName = token.parts[2];
|
|
17976
|
+
}
|
|
17977
|
+
else {
|
|
17978
|
+
prefix = token.parts[0];
|
|
17979
|
+
tagName = token.parts[1];
|
|
17980
|
+
}
|
|
17981
|
+
prefix = prefix || this._getTagDefinition(tagName)?.implicitNamespacePrefix || '';
|
|
17982
|
+
if (!prefix && parent) {
|
|
17983
|
+
const parentName = parent instanceof Element ? parent.name : parent.tagName;
|
|
17984
|
+
if (parentName !== null) {
|
|
17985
|
+
const parentTagName = splitNsName(parentName)[1];
|
|
17986
|
+
const parentTagDefinition = this._getTagDefinition(parentTagName);
|
|
17987
|
+
if (parentTagDefinition !== null && !parentTagDefinition.preventNamespaceInheritance) {
|
|
17988
|
+
prefix = getNsPrefix(parentName);
|
|
17559
17989
|
}
|
|
17560
17990
|
}
|
|
17561
17991
|
}
|
|
17562
|
-
return
|
|
17992
|
+
return prefix;
|
|
17563
17993
|
}
|
|
17564
17994
|
}
|
|
17565
17995
|
function lastOnStack(stack, element) {
|
|
@@ -17638,11 +18068,11 @@ class WhitespaceVisitor {
|
|
|
17638
18068
|
if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
|
|
17639
18069
|
// don't descent into elements where we need to preserve whitespaces
|
|
17640
18070
|
// but still visit all attributes to eliminate one used as a market to preserve WS
|
|
17641
|
-
const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
18071
|
+
const newElement = new Element(element.name, visitAllWithSiblings(this, element.attrs), visitAllWithSiblings(this, element.directives), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
17642
18072
|
this.originalNodeMap?.set(newElement, element);
|
|
17643
18073
|
return newElement;
|
|
17644
18074
|
}
|
|
17645
|
-
const newElement = new Element(element.name, element.attrs, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
18075
|
+
const newElement = new Element(element.name, element.attrs, element.directives, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
17646
18076
|
this.originalNodeMap?.set(newElement, element);
|
|
17647
18077
|
return newElement;
|
|
17648
18078
|
}
|
|
@@ -17716,6 +18146,22 @@ class WhitespaceVisitor {
|
|
|
17716
18146
|
visitLetDeclaration(decl, context) {
|
|
17717
18147
|
return decl;
|
|
17718
18148
|
}
|
|
18149
|
+
visitComponent(node, context) {
|
|
18150
|
+
if ((node.tagName && SKIP_WS_TRIM_TAGS.has(node.tagName)) ||
|
|
18151
|
+
hasPreserveWhitespacesAttr(node.attrs)) {
|
|
18152
|
+
// don't descent into elements where we need to preserve whitespaces
|
|
18153
|
+
// but still visit all attributes to eliminate one used as a market to preserve WS
|
|
18154
|
+
const newElement = new Component(node.componentName, node.tagName, node.fullName, visitAllWithSiblings(this, node.attrs), visitAllWithSiblings(this, node.directives), node.children, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
|
|
18155
|
+
this.originalNodeMap?.set(newElement, node);
|
|
18156
|
+
return newElement;
|
|
18157
|
+
}
|
|
18158
|
+
const newElement = new Component(node.componentName, node.tagName, node.fullName, node.attrs, node.directives, visitAllWithSiblings(this, node.children), node.sourceSpan, node.startSourceSpan, node.endSourceSpan, node.i18n);
|
|
18159
|
+
this.originalNodeMap?.set(newElement, node);
|
|
18160
|
+
return newElement;
|
|
18161
|
+
}
|
|
18162
|
+
visitDirective(directive, context) {
|
|
18163
|
+
return directive;
|
|
18164
|
+
}
|
|
17719
18165
|
visit(_node, context) {
|
|
17720
18166
|
// `visitAllWithSiblings` provides context necessary for ICU messages to be handled correctly.
|
|
17721
18167
|
// Prefer that over calling `html.visitAll` directly on this visitor.
|
|
@@ -19961,6 +20407,7 @@ const SCHEMA = [
|
|
|
19961
20407
|
'q,blockquote,cite^[HTMLElement]|',
|
|
19962
20408
|
'script^[HTMLElement]|!async,charset,%crossOrigin,!defer,event,htmlFor,integrity,!noModule,%referrerPolicy,src,text,type',
|
|
19963
20409
|
'select^[HTMLElement]|autocomplete,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value',
|
|
20410
|
+
'selectedcontent^[HTMLElement]|',
|
|
19964
20411
|
'slot^[HTMLElement]|name',
|
|
19965
20412
|
'source^[HTMLElement]|#height,media,sizes,src,srcset,type,#width',
|
|
19966
20413
|
'span^[HTMLElement]|',
|
|
@@ -20615,28 +21062,13 @@ class _I18nVisitor {
|
|
|
20615
21062
|
return new Message(i18nodes, context.placeholderToContent, context.placeholderToMessage, meaning, description, customId);
|
|
20616
21063
|
}
|
|
20617
21064
|
visitElement(el, context) {
|
|
20618
|
-
|
|
20619
|
-
|
|
20620
|
-
|
|
20621
|
-
|
|
20622
|
-
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid);
|
|
20626
|
-
context.placeholderToContent[startPhName] = {
|
|
20627
|
-
text: el.startSourceSpan.toString(),
|
|
20628
|
-
sourceSpan: el.startSourceSpan,
|
|
20629
|
-
};
|
|
20630
|
-
let closePhName = '';
|
|
20631
|
-
if (!isVoid) {
|
|
20632
|
-
closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(el.name);
|
|
20633
|
-
context.placeholderToContent[closePhName] = {
|
|
20634
|
-
text: `</${el.name}>`,
|
|
20635
|
-
sourceSpan: el.endSourceSpan ?? el.sourceSpan,
|
|
20636
|
-
};
|
|
20637
|
-
}
|
|
20638
|
-
const node = new TagPlaceholder(el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
|
|
20639
|
-
return context.visitNodeFn(el, node);
|
|
21065
|
+
return this._visitElementLike(el, context);
|
|
21066
|
+
}
|
|
21067
|
+
visitComponent(component, context) {
|
|
21068
|
+
return this._visitElementLike(component, context);
|
|
21069
|
+
}
|
|
21070
|
+
visitDirective(directive, context) {
|
|
21071
|
+
throw new Error('Unreachable code');
|
|
20640
21072
|
}
|
|
20641
21073
|
visitAttribute(attribute, context) {
|
|
20642
21074
|
const node = attribute.valueTokens === undefined || attribute.valueTokens.length === 1
|
|
@@ -20710,6 +21142,41 @@ class _I18nVisitor {
|
|
|
20710
21142
|
visitLetDeclaration(decl, context) {
|
|
20711
21143
|
return null;
|
|
20712
21144
|
}
|
|
21145
|
+
_visitElementLike(node, context) {
|
|
21146
|
+
const children = visitAll(this, node.children, context);
|
|
21147
|
+
const attrs = {};
|
|
21148
|
+
const visitAttribute = (attr) => {
|
|
21149
|
+
// Do not visit the attributes, translatable ones are top-level ASTs
|
|
21150
|
+
attrs[attr.name] = attr.value;
|
|
21151
|
+
};
|
|
21152
|
+
let nodeName;
|
|
21153
|
+
let isVoid;
|
|
21154
|
+
if (node instanceof Element) {
|
|
21155
|
+
nodeName = node.name;
|
|
21156
|
+
isVoid = getHtmlTagDefinition(node.name).isVoid;
|
|
21157
|
+
}
|
|
21158
|
+
else {
|
|
21159
|
+
nodeName = node.fullName;
|
|
21160
|
+
isVoid = node.tagName ? getHtmlTagDefinition(node.tagName).isVoid : false;
|
|
21161
|
+
}
|
|
21162
|
+
node.attrs.forEach(visitAttribute);
|
|
21163
|
+
node.directives.forEach((dir) => dir.attrs.forEach(visitAttribute));
|
|
21164
|
+
const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(nodeName, attrs, isVoid);
|
|
21165
|
+
context.placeholderToContent[startPhName] = {
|
|
21166
|
+
text: node.startSourceSpan.toString(),
|
|
21167
|
+
sourceSpan: node.startSourceSpan,
|
|
21168
|
+
};
|
|
21169
|
+
let closePhName = '';
|
|
21170
|
+
if (!isVoid) {
|
|
21171
|
+
closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(nodeName);
|
|
21172
|
+
context.placeholderToContent[closePhName] = {
|
|
21173
|
+
text: `</${nodeName}>`,
|
|
21174
|
+
sourceSpan: node.endSourceSpan ?? node.sourceSpan,
|
|
21175
|
+
};
|
|
21176
|
+
}
|
|
21177
|
+
const i18nNode = new TagPlaceholder(nodeName, attrs, startPhName, closePhName, children, isVoid, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
21178
|
+
return context.visitNodeFn(node, i18nNode);
|
|
21179
|
+
}
|
|
20713
21180
|
/**
|
|
20714
21181
|
* Convert, text and interpolated tokens up into text and placeholder pieces.
|
|
20715
21182
|
*
|
|
@@ -20972,15 +21439,74 @@ class I18nMetaVisitor {
|
|
|
20972
21439
|
return new ParseTreeResult(result, this._errors);
|
|
20973
21440
|
}
|
|
20974
21441
|
visitElement(element) {
|
|
21442
|
+
this._visitElementLike(element);
|
|
21443
|
+
return element;
|
|
21444
|
+
}
|
|
21445
|
+
visitComponent(component, context) {
|
|
21446
|
+
this._visitElementLike(component);
|
|
21447
|
+
return component;
|
|
21448
|
+
}
|
|
21449
|
+
visitExpansion(expansion, currentMessage) {
|
|
21450
|
+
let message;
|
|
21451
|
+
const meta = expansion.i18n;
|
|
21452
|
+
this.hasI18nMeta = true;
|
|
21453
|
+
if (meta instanceof IcuPlaceholder) {
|
|
21454
|
+
// set ICU placeholder name (e.g. "ICU_1"),
|
|
21455
|
+
// generated while processing root element contents,
|
|
21456
|
+
// so we can reference it when we output translation
|
|
21457
|
+
const name = meta.name;
|
|
21458
|
+
message = this._generateI18nMessage([expansion], meta);
|
|
21459
|
+
const icu = icuFromI18nMessage(message);
|
|
21460
|
+
icu.name = name;
|
|
21461
|
+
if (currentMessage !== null) {
|
|
21462
|
+
// Also update the placeholderToMessage map with this new message
|
|
21463
|
+
currentMessage.placeholderToMessage[name] = message;
|
|
21464
|
+
}
|
|
21465
|
+
}
|
|
21466
|
+
else {
|
|
21467
|
+
// ICU is a top level message, try to use metadata from container element if provided via
|
|
21468
|
+
// `context` argument. Note: context may not be available for standalone ICUs (without
|
|
21469
|
+
// wrapping element), so fallback to ICU metadata in this case.
|
|
21470
|
+
message = this._generateI18nMessage([expansion], currentMessage || meta);
|
|
21471
|
+
}
|
|
21472
|
+
expansion.i18n = message;
|
|
21473
|
+
return expansion;
|
|
21474
|
+
}
|
|
21475
|
+
visitText(text) {
|
|
21476
|
+
return text;
|
|
21477
|
+
}
|
|
21478
|
+
visitAttribute(attribute) {
|
|
21479
|
+
return attribute;
|
|
21480
|
+
}
|
|
21481
|
+
visitComment(comment) {
|
|
21482
|
+
return comment;
|
|
21483
|
+
}
|
|
21484
|
+
visitExpansionCase(expansionCase) {
|
|
21485
|
+
return expansionCase;
|
|
21486
|
+
}
|
|
21487
|
+
visitBlock(block, context) {
|
|
21488
|
+
visitAll(this, block.children, context);
|
|
21489
|
+
return block;
|
|
21490
|
+
}
|
|
21491
|
+
visitBlockParameter(parameter, context) {
|
|
21492
|
+
return parameter;
|
|
21493
|
+
}
|
|
21494
|
+
visitLetDeclaration(decl, context) {
|
|
21495
|
+
return decl;
|
|
21496
|
+
}
|
|
21497
|
+
visitDirective(directive, context) {
|
|
21498
|
+
return directive;
|
|
21499
|
+
}
|
|
21500
|
+
_visitElementLike(node) {
|
|
20975
21501
|
let message = undefined;
|
|
20976
|
-
if (hasI18nAttrs(
|
|
21502
|
+
if (hasI18nAttrs(node)) {
|
|
20977
21503
|
this.hasI18nMeta = true;
|
|
20978
21504
|
const attrs = [];
|
|
20979
21505
|
const attrsMeta = {};
|
|
20980
|
-
for (const attr of
|
|
21506
|
+
for (const attr of node.attrs) {
|
|
20981
21507
|
if (attr.name === I18N_ATTR) {
|
|
20982
21508
|
// root 'i18n' node attribute
|
|
20983
|
-
const i18n =
|
|
21509
|
+
const i18n = node.i18n || attr.value;
|
|
20984
21510
|
// Generate a new AST with whitespace trimmed, but also generate a map
|
|
20985
21511
|
// to correlate each new node to its original so we can apply i18n
|
|
20986
21512
|
// information to the original node based on the trimmed content.
|
|
@@ -20994,20 +21520,27 @@ class I18nMetaVisitor {
|
|
|
20994
21520
|
// backwards compatibility.
|
|
20995
21521
|
const originalNodeMap = new Map();
|
|
20996
21522
|
const trimmedNodes = this.preserveSignificantWhitespace
|
|
20997
|
-
?
|
|
20998
|
-
: visitAllWithSiblings(new WhitespaceVisitor(false /* preserveSignificantWhitespace */, originalNodeMap),
|
|
21523
|
+
? node.children
|
|
21524
|
+
: visitAllWithSiblings(new WhitespaceVisitor(false /* preserveSignificantWhitespace */, originalNodeMap), node.children);
|
|
20999
21525
|
message = this._generateI18nMessage(trimmedNodes, i18n, setI18nRefs(originalNodeMap));
|
|
21000
21526
|
if (message.nodes.length === 0) {
|
|
21001
21527
|
// Ignore the message if it is empty.
|
|
21002
21528
|
message = undefined;
|
|
21003
21529
|
}
|
|
21004
21530
|
// Store the message on the element
|
|
21005
|
-
|
|
21531
|
+
node.i18n = message;
|
|
21006
21532
|
}
|
|
21007
21533
|
else if (attr.name.startsWith(I18N_ATTR_PREFIX)) {
|
|
21008
21534
|
// 'i18n-*' attributes
|
|
21009
21535
|
const name = attr.name.slice(I18N_ATTR_PREFIX.length);
|
|
21010
|
-
|
|
21536
|
+
let isTrustedType;
|
|
21537
|
+
if (node instanceof Component) {
|
|
21538
|
+
isTrustedType = node.tagName === null ? false : isTrustedTypesSink(node.tagName, name);
|
|
21539
|
+
}
|
|
21540
|
+
else {
|
|
21541
|
+
isTrustedType = isTrustedTypesSink(node.name, name);
|
|
21542
|
+
}
|
|
21543
|
+
if (isTrustedType) {
|
|
21011
21544
|
this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`);
|
|
21012
21545
|
}
|
|
21013
21546
|
else {
|
|
@@ -21032,59 +21565,10 @@ class I18nMetaVisitor {
|
|
|
21032
21565
|
if (!this.keepI18nAttrs) {
|
|
21033
21566
|
// update element's attributes,
|
|
21034
21567
|
// keeping only non-i18n related ones
|
|
21035
|
-
|
|
21036
|
-
}
|
|
21037
|
-
}
|
|
21038
|
-
visitAll(this, element.children, message);
|
|
21039
|
-
return element;
|
|
21040
|
-
}
|
|
21041
|
-
visitExpansion(expansion, currentMessage) {
|
|
21042
|
-
let message;
|
|
21043
|
-
const meta = expansion.i18n;
|
|
21044
|
-
this.hasI18nMeta = true;
|
|
21045
|
-
if (meta instanceof IcuPlaceholder) {
|
|
21046
|
-
// set ICU placeholder name (e.g. "ICU_1"),
|
|
21047
|
-
// generated while processing root element contents,
|
|
21048
|
-
// so we can reference it when we output translation
|
|
21049
|
-
const name = meta.name;
|
|
21050
|
-
message = this._generateI18nMessage([expansion], meta);
|
|
21051
|
-
const icu = icuFromI18nMessage(message);
|
|
21052
|
-
icu.name = name;
|
|
21053
|
-
if (currentMessage !== null) {
|
|
21054
|
-
// Also update the placeholderToMessage map with this new message
|
|
21055
|
-
currentMessage.placeholderToMessage[name] = message;
|
|
21568
|
+
node.attrs = attrs;
|
|
21056
21569
|
}
|
|
21057
21570
|
}
|
|
21058
|
-
|
|
21059
|
-
// ICU is a top level message, try to use metadata from container element if provided via
|
|
21060
|
-
// `context` argument. Note: context may not be available for standalone ICUs (without
|
|
21061
|
-
// wrapping element), so fallback to ICU metadata in this case.
|
|
21062
|
-
message = this._generateI18nMessage([expansion], currentMessage || meta);
|
|
21063
|
-
}
|
|
21064
|
-
expansion.i18n = message;
|
|
21065
|
-
return expansion;
|
|
21066
|
-
}
|
|
21067
|
-
visitText(text) {
|
|
21068
|
-
return text;
|
|
21069
|
-
}
|
|
21070
|
-
visitAttribute(attribute) {
|
|
21071
|
-
return attribute;
|
|
21072
|
-
}
|
|
21073
|
-
visitComment(comment) {
|
|
21074
|
-
return comment;
|
|
21075
|
-
}
|
|
21076
|
-
visitExpansionCase(expansionCase) {
|
|
21077
|
-
return expansionCase;
|
|
21078
|
-
}
|
|
21079
|
-
visitBlock(block, context) {
|
|
21080
|
-
visitAll(this, block.children, context);
|
|
21081
|
-
return block;
|
|
21082
|
-
}
|
|
21083
|
-
visitBlockParameter(parameter, context) {
|
|
21084
|
-
return parameter;
|
|
21085
|
-
}
|
|
21086
|
-
visitLetDeclaration(decl, context) {
|
|
21087
|
-
return decl;
|
|
21571
|
+
visitAll(this, node.children, message);
|
|
21088
21572
|
}
|
|
21089
21573
|
/**
|
|
21090
21574
|
* Parse the general form `meta` passed into extract the explicit metadata needed to create a
|
|
@@ -22004,7 +22488,7 @@ function addNamesToView(unit, baseName, state, compatibility) {
|
|
|
22004
22488
|
for (const op of unit.ops()) {
|
|
22005
22489
|
switch (op.kind) {
|
|
22006
22490
|
case OpKind.Property:
|
|
22007
|
-
case OpKind.
|
|
22491
|
+
case OpKind.DomProperty:
|
|
22008
22492
|
if (op.isAnimationTrigger) {
|
|
22009
22493
|
op.name = '@' + op.name;
|
|
22010
22494
|
}
|
|
@@ -22320,8 +22804,8 @@ const UPDATE_ORDERING = [
|
|
|
22320
22804
|
* Host bindings have their own update ordering.
|
|
22321
22805
|
*/
|
|
22322
22806
|
const UPDATE_HOST_ORDERING = [
|
|
22323
|
-
{ test: kindWithInterpolationTest(OpKind.
|
|
22324
|
-
{ test: kindWithInterpolationTest(OpKind.
|
|
22807
|
+
{ test: kindWithInterpolationTest(OpKind.DomProperty, true) },
|
|
22808
|
+
{ test: kindWithInterpolationTest(OpKind.DomProperty, false) },
|
|
22325
22809
|
{ test: kindTest(OpKind.Attribute) },
|
|
22326
22810
|
{ test: kindTest(OpKind.StyleMap), transform: keepLast },
|
|
22327
22811
|
{ test: kindTest(OpKind.ClassMap), transform: keepLast },
|
|
@@ -22340,7 +22824,7 @@ const handledOpKinds = new Set([
|
|
|
22340
22824
|
OpKind.ClassProp,
|
|
22341
22825
|
OpKind.Property,
|
|
22342
22826
|
OpKind.TwoWayProperty,
|
|
22343
|
-
OpKind.
|
|
22827
|
+
OpKind.DomProperty,
|
|
22344
22828
|
OpKind.Attribute,
|
|
22345
22829
|
]);
|
|
22346
22830
|
/**
|
|
@@ -23114,12 +23598,12 @@ function classMapInterpolate(strings, expressions, sourceSpan) {
|
|
|
23114
23598
|
const interpolationArgs = collateInterpolationArgs(strings, expressions);
|
|
23115
23599
|
return callVariadicInstruction(CLASS_MAP_INTERPOLATE_CONFIG, [], interpolationArgs, [], sourceSpan);
|
|
23116
23600
|
}
|
|
23117
|
-
function
|
|
23601
|
+
function domProperty(name, expression, sanitizer, sourceSpan) {
|
|
23118
23602
|
const args = [literal(name), expression];
|
|
23119
23603
|
if (sanitizer !== null) {
|
|
23120
23604
|
args.push(sanitizer);
|
|
23121
23605
|
}
|
|
23122
|
-
return call(Identifiers.
|
|
23606
|
+
return call(Identifiers.domProperty, args, sourceSpan);
|
|
23123
23607
|
}
|
|
23124
23608
|
function syntheticHostProperty(name, expression, sourceSpan) {
|
|
23125
23609
|
return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
|
|
@@ -23658,7 +24142,7 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
23658
24142
|
OpList.replace(op, attribute(op.name, op.expression, op.sanitizer, op.namespace));
|
|
23659
24143
|
}
|
|
23660
24144
|
break;
|
|
23661
|
-
case OpKind.
|
|
24145
|
+
case OpKind.DomProperty:
|
|
23662
24146
|
if (op.expression instanceof Interpolation) {
|
|
23663
24147
|
throw new Error('not yet handled');
|
|
23664
24148
|
}
|
|
@@ -23667,7 +24151,7 @@ function reifyUpdateOperations(_unit, ops) {
|
|
|
23667
24151
|
OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
|
|
23668
24152
|
}
|
|
23669
24153
|
else {
|
|
23670
|
-
OpList.replace(op,
|
|
24154
|
+
OpList.replace(op, domProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
|
|
23671
24155
|
}
|
|
23672
24156
|
}
|
|
23673
24157
|
break;
|
|
@@ -24501,7 +24985,7 @@ function resolveSanitizers(job) {
|
|
|
24501
24985
|
switch (op.kind) {
|
|
24502
24986
|
case OpKind.Property:
|
|
24503
24987
|
case OpKind.Attribute:
|
|
24504
|
-
case OpKind.
|
|
24988
|
+
case OpKind.DomProperty:
|
|
24505
24989
|
let sanitizerFn = null;
|
|
24506
24990
|
if (Array.isArray(op.securityContext) &&
|
|
24507
24991
|
op.securityContext.length === 2 &&
|
|
@@ -24523,7 +25007,7 @@ function resolveSanitizers(job) {
|
|
|
24523
25007
|
// <iframe>).
|
|
24524
25008
|
if (op.sanitizer === null) {
|
|
24525
25009
|
let isIframe = false;
|
|
24526
|
-
if (job.kind === CompilationJobKind.Host || op.kind === OpKind.
|
|
25010
|
+
if (job.kind === CompilationJobKind.Host || op.kind === OpKind.DomProperty) {
|
|
24527
25011
|
// Note: for host bindings defined on a directive, we do not try to find all
|
|
24528
25012
|
// possible places where it can be matched, so we can not determine whether
|
|
24529
25013
|
// the host element is an <iframe>. In this case, we just assume it is and append a
|
|
@@ -25130,7 +25614,7 @@ function varsUsedByOp(op) {
|
|
|
25130
25614
|
let slots;
|
|
25131
25615
|
switch (op.kind) {
|
|
25132
25616
|
case OpKind.Property:
|
|
25133
|
-
case OpKind.
|
|
25617
|
+
case OpKind.DomProperty:
|
|
25134
25618
|
case OpKind.Attribute:
|
|
25135
25619
|
// All of these bindings use 1 variable slot, plus 1 slot for every interpolated expression,
|
|
25136
25620
|
// if any.
|
|
@@ -25859,7 +26343,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
25859
26343
|
const securityContexts = bindingParser
|
|
25860
26344
|
.calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
|
|
25861
26345
|
.filter((context) => context !== SecurityContext.NONE);
|
|
25862
|
-
|
|
26346
|
+
ingestDomProperty(job, property, bindingKind, securityContexts);
|
|
25863
26347
|
}
|
|
25864
26348
|
for (const [name, expr] of Object.entries(input.attributes) ?? []) {
|
|
25865
26349
|
const securityContexts = bindingParser
|
|
@@ -25874,7 +26358,7 @@ function ingestHostBinding(input, bindingParser, constantPool) {
|
|
|
25874
26358
|
}
|
|
25875
26359
|
// TODO: We should refactor the parser to use the same types and structures for host bindings as
|
|
25876
26360
|
// with ordinary components. This would allow us to share a lot more ingestion code.
|
|
25877
|
-
function
|
|
26361
|
+
function ingestDomProperty(job, property, bindingKind, securityContexts) {
|
|
25878
26362
|
let expression;
|
|
25879
26363
|
const ast = property.expression.ast;
|
|
25880
26364
|
if (ast instanceof Interpolation$1) {
|
|
@@ -27392,10 +27876,16 @@ class BindingParser {
|
|
|
27392
27876
|
const prop = this._schemaRegistry.getMappedPropName(propName);
|
|
27393
27877
|
return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
|
|
27394
27878
|
}
|
|
27879
|
+
parseEventListenerName(rawName) {
|
|
27880
|
+
const [target, eventName] = splitAtColon(rawName, [null, rawName]);
|
|
27881
|
+
return { eventName: eventName, target };
|
|
27882
|
+
}
|
|
27883
|
+
parseAnimationEventName(rawName) {
|
|
27884
|
+
const matches = splitAtPeriod(rawName, [rawName, null]);
|
|
27885
|
+
return { eventName: matches[0], phase: matches[1] === null ? null : matches[1].toLowerCase() };
|
|
27886
|
+
}
|
|
27395
27887
|
_parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents, keySpan) {
|
|
27396
|
-
const
|
|
27397
|
-
const eventName = matches[0];
|
|
27398
|
-
const phase = matches[1].toLowerCase();
|
|
27888
|
+
const { eventName, phase } = this.parseAnimationEventName(name);
|
|
27399
27889
|
const ast = this._parseAction(expression, handlerSpan);
|
|
27400
27890
|
targetEvents.push(new ParsedEvent(eventName, phase, ParsedEventType.Animation, ast, sourceSpan, handlerSpan, keySpan));
|
|
27401
27891
|
if (eventName.length === 0) {
|
|
@@ -27412,7 +27902,7 @@ class BindingParser {
|
|
|
27412
27902
|
}
|
|
27413
27903
|
_parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
|
|
27414
27904
|
// long format: 'target: eventName'
|
|
27415
|
-
const
|
|
27905
|
+
const { eventName, target } = this.parseEventListenerName(name);
|
|
27416
27906
|
const prevErrorCount = this.errors.length;
|
|
27417
27907
|
const ast = this._parseAction(expression, handlerSpan);
|
|
27418
27908
|
const isValid = this.errors.length === prevErrorCount;
|
|
@@ -27495,15 +27985,22 @@ function isAnimationLabel(name) {
|
|
|
27495
27985
|
return name[0] == '@';
|
|
27496
27986
|
}
|
|
27497
27987
|
function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
|
|
27503
|
-
|
|
27504
|
-
|
|
27505
|
-
|
|
27506
|
-
|
|
27988
|
+
let ctxs;
|
|
27989
|
+
const nameToContext = (elName) => registry.securityContext(elName, propName, isAttribute);
|
|
27990
|
+
if (selector === null) {
|
|
27991
|
+
ctxs = registry.allKnownElementNames().map(nameToContext);
|
|
27992
|
+
}
|
|
27993
|
+
else {
|
|
27994
|
+
ctxs = [];
|
|
27995
|
+
CssSelector.parse(selector).forEach((selector) => {
|
|
27996
|
+
const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
|
|
27997
|
+
const notElementNames = new Set(selector.notSelectors
|
|
27998
|
+
.filter((selector) => selector.isElementSelector())
|
|
27999
|
+
.map((selector) => selector.element));
|
|
28000
|
+
const possibleElementNames = elementNames.filter((elName) => !notElementNames.has(elName));
|
|
28001
|
+
ctxs.push(...possibleElementNames.map(nameToContext));
|
|
28002
|
+
});
|
|
28003
|
+
}
|
|
27507
28004
|
return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
|
|
27508
28005
|
}
|
|
27509
28006
|
/**
|
|
@@ -27616,11 +28113,13 @@ const FOR_LOOP_EXPRESSION_PATTERN = /^\s*([0-9A-Za-z_$]*)\s+of\s+([\S\s]*)/;
|
|
|
27616
28113
|
/** Pattern for the tracking expression in a for loop block. */
|
|
27617
28114
|
const FOR_LOOP_TRACK_PATTERN = /^track\s+([\S\s]*)/;
|
|
27618
28115
|
/** Pattern for the `as` expression in a conditional block. */
|
|
27619
|
-
const CONDITIONAL_ALIAS_PATTERN = /^(as\s)
|
|
28116
|
+
const CONDITIONAL_ALIAS_PATTERN = /^(as\s+)(.*)/;
|
|
27620
28117
|
/** Pattern used to identify an `else if` block. */
|
|
27621
28118
|
const ELSE_IF_PATTERN = /^else[^\S\r\n]+if/;
|
|
27622
28119
|
/** Pattern used to identify a `let` parameter. */
|
|
27623
28120
|
const FOR_LOOP_LET_PATTERN = /^let\s+([\S\s]*)/;
|
|
28121
|
+
/** Pattern used to validate a JavaScript identifier. */
|
|
28122
|
+
const IDENTIFIER_PATTERN = /^[$A-Z_][0-9A-Z_$]*$/i;
|
|
27624
28123
|
/**
|
|
27625
28124
|
* Pattern to group a string into leading whitespace, non whitespace, and trailing whitespace.
|
|
27626
28125
|
* Useful for getting the variable name span when a span can contain leading and trailing space.
|
|
@@ -27968,9 +28467,14 @@ function parseConditionalBlockParameters(block, errors, bindingParser) {
|
|
|
27968
28467
|
}
|
|
27969
28468
|
else {
|
|
27970
28469
|
const name = aliasMatch[2].trim();
|
|
27971
|
-
|
|
27972
|
-
|
|
27973
|
-
|
|
28470
|
+
if (IDENTIFIER_PATTERN.test(name)) {
|
|
28471
|
+
const variableStart = param.sourceSpan.start.moveBy(aliasMatch[1].length);
|
|
28472
|
+
const variableSpan = new ParseSourceSpan(variableStart, variableStart.moveBy(name.length));
|
|
28473
|
+
expressionAlias = new Variable(name, name, variableSpan, variableSpan);
|
|
28474
|
+
}
|
|
28475
|
+
else {
|
|
28476
|
+
errors.push(new ParseError(param.sourceSpan, '"as" expression must be a valid JavaScript identifier'));
|
|
28477
|
+
}
|
|
27974
28478
|
}
|
|
27975
28479
|
}
|
|
27976
28480
|
return { expression, expressionAlias };
|
|
@@ -28581,6 +29085,17 @@ const BINDING_DELIMS = {
|
|
|
28581
29085
|
EVENT: { start: '(', end: ')' },
|
|
28582
29086
|
};
|
|
28583
29087
|
const TEMPLATE_ATTR_PREFIX = '*';
|
|
29088
|
+
// TODO(crisbeto): any other tag names that shouldn't be allowed here?
|
|
29089
|
+
const UNSUPPORTED_SELECTORLESS_TAGS = new Set([
|
|
29090
|
+
'link',
|
|
29091
|
+
'style',
|
|
29092
|
+
'script',
|
|
29093
|
+
'ng-template',
|
|
29094
|
+
'ng-container',
|
|
29095
|
+
'ng-content',
|
|
29096
|
+
]);
|
|
29097
|
+
// TODO(crisbeto): any other attributes that should not be allowed here?
|
|
29098
|
+
const UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS = new Set(['ngProjectAs', 'ngNonBindable']);
|
|
28584
29099
|
function htmlAstToRender3Ast(htmlNodes, bindingParser, options) {
|
|
28585
29100
|
const transformer = new HtmlAstToIvyAst(bindingParser, options);
|
|
28586
29101
|
const ivyNodes = visitAll(transformer, htmlNodes, htmlNodes);
|
|
@@ -28644,52 +29159,8 @@ class HtmlAstToIvyAst {
|
|
|
28644
29159
|
}
|
|
28645
29160
|
// Whether the element is a `<ng-template>`
|
|
28646
29161
|
const isTemplateElement = isNgTemplate(element.name);
|
|
28647
|
-
const parsedProperties =
|
|
28648
|
-
const
|
|
28649
|
-
const variables = [];
|
|
28650
|
-
const references = [];
|
|
28651
|
-
const attributes = [];
|
|
28652
|
-
const i18nAttrsMeta = {};
|
|
28653
|
-
const templateParsedProperties = [];
|
|
28654
|
-
const templateVariables = [];
|
|
28655
|
-
// Whether the element has any *-attribute
|
|
28656
|
-
let elementHasInlineTemplate = false;
|
|
28657
|
-
for (const attribute of element.attrs) {
|
|
28658
|
-
let hasBinding = false;
|
|
28659
|
-
const normalizedName = normalizeAttributeName(attribute.name);
|
|
28660
|
-
// `*attr` defines template bindings
|
|
28661
|
-
let isTemplateBinding = false;
|
|
28662
|
-
if (attribute.i18n) {
|
|
28663
|
-
i18nAttrsMeta[attribute.name] = attribute.i18n;
|
|
28664
|
-
}
|
|
28665
|
-
if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
|
|
28666
|
-
// *-attributes
|
|
28667
|
-
if (elementHasInlineTemplate) {
|
|
28668
|
-
this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
|
|
28669
|
-
}
|
|
28670
|
-
isTemplateBinding = true;
|
|
28671
|
-
elementHasInlineTemplate = true;
|
|
28672
|
-
const templateValue = attribute.value;
|
|
28673
|
-
const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
|
|
28674
|
-
const parsedVariables = [];
|
|
28675
|
-
const absoluteValueOffset = attribute.valueSpan
|
|
28676
|
-
? attribute.valueSpan.start.offset
|
|
28677
|
-
: // If there is no value span the attribute does not have a value, like `attr` in
|
|
28678
|
-
//`<div attr></div>`. In this case, point to one character beyond the last character of
|
|
28679
|
-
// the attribute name.
|
|
28680
|
-
attribute.sourceSpan.start.offset + attribute.name.length;
|
|
28681
|
-
this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true /* isIvyAst */);
|
|
28682
|
-
templateVariables.push(...parsedVariables.map((v) => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
|
|
28683
|
-
}
|
|
28684
|
-
else {
|
|
28685
|
-
// Check for variables, events, property bindings, interpolation
|
|
28686
|
-
hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
|
|
28687
|
-
}
|
|
28688
|
-
if (!hasBinding && !isTemplateBinding) {
|
|
28689
|
-
// don't include the bindings as attributes as well in the AST
|
|
28690
|
-
attributes.push(this.visitAttribute(attribute));
|
|
28691
|
-
}
|
|
28692
|
-
}
|
|
29162
|
+
const { attributes, boundEvents, references, variables, templateVariables, elementHasInlineTemplate, parsedProperties, templateParsedProperties, i18nAttrsMeta, } = this.prepareAttributes(element.attrs, isTemplateElement);
|
|
29163
|
+
const directives = this.extractDirectives(element);
|
|
28693
29164
|
let children;
|
|
28694
29165
|
if (preparsedElement.nonBindable) {
|
|
28695
29166
|
// The `NonBindableVisitor` may need to return an array of nodes for blocks so we need
|
|
@@ -28704,44 +29175,24 @@ class HtmlAstToIvyAst {
|
|
|
28704
29175
|
if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
|
|
28705
29176
|
const selector = preparsedElement.selectAttr;
|
|
28706
29177
|
const attrs = element.attrs.map((attr) => this.visitAttribute(attr));
|
|
28707
|
-
parsedElement = new Content(selector, attrs, children, element.sourceSpan, element.i18n);
|
|
29178
|
+
parsedElement = new Content(selector, attrs, children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
28708
29179
|
this.ngContentSelectors.push(selector);
|
|
28709
29180
|
}
|
|
28710
29181
|
else if (isTemplateElement) {
|
|
28711
29182
|
// `<ng-template>`
|
|
28712
|
-
const attrs = this.
|
|
28713
|
-
parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, [
|
|
29183
|
+
const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
|
|
29184
|
+
parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, directives, [
|
|
28714
29185
|
/* no template attributes */
|
|
28715
29186
|
], children, references, variables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
28716
29187
|
}
|
|
28717
29188
|
else {
|
|
28718
|
-
const attrs = this.
|
|
28719
|
-
parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
29189
|
+
const attrs = this.categorizePropertyAttributes(element.name, parsedProperties, i18nAttrsMeta);
|
|
29190
|
+
parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, directives, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
|
|
28720
29191
|
}
|
|
28721
29192
|
if (elementHasInlineTemplate) {
|
|
28722
29193
|
// If this node is an inline-template (e.g. has *ngFor) then we need to create a template
|
|
28723
29194
|
// node that contains this node.
|
|
28724
|
-
|
|
28725
|
-
// node for matching against content projection selectors.
|
|
28726
|
-
const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta);
|
|
28727
|
-
const templateAttrs = [];
|
|
28728
|
-
attrs.literal.forEach((attr) => templateAttrs.push(attr));
|
|
28729
|
-
attrs.bound.forEach((attr) => templateAttrs.push(attr));
|
|
28730
|
-
const hoistedAttrs = parsedElement instanceof Element$1
|
|
28731
|
-
? {
|
|
28732
|
-
attributes: parsedElement.attributes,
|
|
28733
|
-
inputs: parsedElement.inputs,
|
|
28734
|
-
outputs: parsedElement.outputs,
|
|
28735
|
-
}
|
|
28736
|
-
: { attributes: [], inputs: [], outputs: [] };
|
|
28737
|
-
// For <ng-template>s with structural directives on them, avoid passing i18n information to
|
|
28738
|
-
// the wrapping template to prevent unnecessary i18n instructions from being generated. The
|
|
28739
|
-
// necessary i18n meta information will be extracted from child elements.
|
|
28740
|
-
const i18n = isTemplateElement && isI18nRootElement ? undefined : element.i18n;
|
|
28741
|
-
const name = parsedElement instanceof Template ? null : parsedElement.name;
|
|
28742
|
-
parsedElement = new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, templateAttrs, [parsedElement], [
|
|
28743
|
-
/* no references */
|
|
28744
|
-
], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, i18n);
|
|
29195
|
+
parsedElement = this.wrapInTemplate(parsedElement, templateParsedProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement);
|
|
28745
29196
|
}
|
|
28746
29197
|
if (isI18nRootElement) {
|
|
28747
29198
|
this.inI18nBlock = false;
|
|
@@ -28805,6 +29256,43 @@ class HtmlAstToIvyAst {
|
|
|
28805
29256
|
}
|
|
28806
29257
|
return new LetDeclaration$1(decl.name, value, decl.sourceSpan, decl.nameSpan, decl.valueSpan);
|
|
28807
29258
|
}
|
|
29259
|
+
visitComponent(component) {
|
|
29260
|
+
const isI18nRootElement = isI18nRootNode(component.i18n);
|
|
29261
|
+
if (isI18nRootElement) {
|
|
29262
|
+
if (this.inI18nBlock) {
|
|
29263
|
+
this.reportError('Cannot mark a component as translatable inside of a translatable section. Please remove the nested i18n marker.', component.sourceSpan);
|
|
29264
|
+
}
|
|
29265
|
+
this.inI18nBlock = true;
|
|
29266
|
+
}
|
|
29267
|
+
if (component.tagName !== null && UNSUPPORTED_SELECTORLESS_TAGS.has(component.tagName)) {
|
|
29268
|
+
this.reportError(`Tag name "${component.tagName}" cannot be used as a component tag`, component.startSourceSpan);
|
|
29269
|
+
return null;
|
|
29270
|
+
}
|
|
29271
|
+
const { attributes, boundEvents, references, templateVariables, elementHasInlineTemplate, parsedProperties, templateParsedProperties, i18nAttrsMeta, } = this.prepareAttributes(component.attrs, false);
|
|
29272
|
+
const directives = this.extractDirectives(component);
|
|
29273
|
+
let children;
|
|
29274
|
+
if (component.attrs.find((attr) => attr.name === 'ngNonBindable')) {
|
|
29275
|
+
// The `NonBindableVisitor` may need to return an array of nodes for blocks so we need
|
|
29276
|
+
// to flatten the array here. Avoid doing this for the `HtmlAstToIvyAst` since `flat` creates
|
|
29277
|
+
// a new array.
|
|
29278
|
+
children = visitAll(NON_BINDABLE_VISITOR, component.children).flat(Infinity);
|
|
29279
|
+
}
|
|
29280
|
+
else {
|
|
29281
|
+
children = visitAll(this, component.children, component.children);
|
|
29282
|
+
}
|
|
29283
|
+
const attrs = this.categorizePropertyAttributes(component.tagName, parsedProperties, i18nAttrsMeta);
|
|
29284
|
+
let node = new Component$1(component.componentName, component.tagName, component.fullName, attributes, attrs.bound, boundEvents, directives, children, references, component.sourceSpan, component.startSourceSpan, component.endSourceSpan, component.i18n);
|
|
29285
|
+
if (elementHasInlineTemplate) {
|
|
29286
|
+
node = this.wrapInTemplate(node, templateParsedProperties, templateVariables, i18nAttrsMeta, false, isI18nRootElement);
|
|
29287
|
+
}
|
|
29288
|
+
if (isI18nRootElement) {
|
|
29289
|
+
this.inI18nBlock = false;
|
|
29290
|
+
}
|
|
29291
|
+
return node;
|
|
29292
|
+
}
|
|
29293
|
+
visitDirective() {
|
|
29294
|
+
return null;
|
|
29295
|
+
}
|
|
28808
29296
|
visitBlockParameter() {
|
|
28809
29297
|
return null;
|
|
28810
29298
|
}
|
|
@@ -28881,8 +29369,8 @@ class HtmlAstToIvyAst {
|
|
|
28881
29369
|
}
|
|
28882
29370
|
return relatedBlocks;
|
|
28883
29371
|
}
|
|
28884
|
-
|
|
28885
|
-
|
|
29372
|
+
/** Splits up the property attributes depending on whether they're static or bound. */
|
|
29373
|
+
categorizePropertyAttributes(elementName, properties, i18nPropsMeta) {
|
|
28886
29374
|
const bound = [];
|
|
28887
29375
|
const literal = [];
|
|
28888
29376
|
properties.forEach((prop) => {
|
|
@@ -28902,6 +29390,65 @@ class HtmlAstToIvyAst {
|
|
|
28902
29390
|
});
|
|
28903
29391
|
return { bound, literal };
|
|
28904
29392
|
}
|
|
29393
|
+
prepareAttributes(attrs, isTemplateElement) {
|
|
29394
|
+
const parsedProperties = [];
|
|
29395
|
+
const boundEvents = [];
|
|
29396
|
+
const variables = [];
|
|
29397
|
+
const references = [];
|
|
29398
|
+
const attributes = [];
|
|
29399
|
+
const i18nAttrsMeta = {};
|
|
29400
|
+
const templateParsedProperties = [];
|
|
29401
|
+
const templateVariables = [];
|
|
29402
|
+
// Whether the element has any *-attribute
|
|
29403
|
+
let elementHasInlineTemplate = false;
|
|
29404
|
+
for (const attribute of attrs) {
|
|
29405
|
+
let hasBinding = false;
|
|
29406
|
+
const normalizedName = normalizeAttributeName(attribute.name);
|
|
29407
|
+
// `*attr` defines template bindings
|
|
29408
|
+
let isTemplateBinding = false;
|
|
29409
|
+
if (attribute.i18n) {
|
|
29410
|
+
i18nAttrsMeta[attribute.name] = attribute.i18n;
|
|
29411
|
+
}
|
|
29412
|
+
if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
|
|
29413
|
+
// *-attributes
|
|
29414
|
+
if (elementHasInlineTemplate) {
|
|
29415
|
+
this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
|
|
29416
|
+
}
|
|
29417
|
+
isTemplateBinding = true;
|
|
29418
|
+
elementHasInlineTemplate = true;
|
|
29419
|
+
const templateValue = attribute.value;
|
|
29420
|
+
const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
|
|
29421
|
+
const parsedVariables = [];
|
|
29422
|
+
const absoluteValueOffset = attribute.valueSpan
|
|
29423
|
+
? attribute.valueSpan.start.offset
|
|
29424
|
+
: // If there is no value span the attribute does not have a value, like `attr` in
|
|
29425
|
+
//`<div attr></div>`. In this case, point to one character beyond the last character of
|
|
29426
|
+
// the attribute name.
|
|
29427
|
+
attribute.sourceSpan.start.offset + attribute.name.length;
|
|
29428
|
+
this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true /* isIvyAst */);
|
|
29429
|
+
templateVariables.push(...parsedVariables.map((v) => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
|
|
29430
|
+
}
|
|
29431
|
+
else {
|
|
29432
|
+
// Check for variables, events, property bindings, interpolation
|
|
29433
|
+
hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
|
|
29434
|
+
}
|
|
29435
|
+
if (!hasBinding && !isTemplateBinding) {
|
|
29436
|
+
// don't include the bindings as attributes as well in the AST
|
|
29437
|
+
attributes.push(this.visitAttribute(attribute));
|
|
29438
|
+
}
|
|
29439
|
+
}
|
|
29440
|
+
return {
|
|
29441
|
+
attributes,
|
|
29442
|
+
boundEvents,
|
|
29443
|
+
references,
|
|
29444
|
+
variables,
|
|
29445
|
+
templateVariables,
|
|
29446
|
+
elementHasInlineTemplate,
|
|
29447
|
+
parsedProperties,
|
|
29448
|
+
templateParsedProperties,
|
|
29449
|
+
i18nAttrsMeta,
|
|
29450
|
+
};
|
|
29451
|
+
}
|
|
28905
29452
|
parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) {
|
|
28906
29453
|
const name = normalizeAttributeName(attribute.name);
|
|
28907
29454
|
const value = attribute.value;
|
|
@@ -29000,6 +29547,81 @@ class HtmlAstToIvyAst {
|
|
|
29000
29547
|
const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null);
|
|
29001
29548
|
return hasBinding;
|
|
29002
29549
|
}
|
|
29550
|
+
extractDirectives(node) {
|
|
29551
|
+
const elementName = node instanceof Component ? node.tagName : node.name;
|
|
29552
|
+
const directives = [];
|
|
29553
|
+
const seenDirectives = new Set();
|
|
29554
|
+
for (const directive of node.directives) {
|
|
29555
|
+
let invalid = false;
|
|
29556
|
+
for (const attr of directive.attrs) {
|
|
29557
|
+
if (attr.name.startsWith(TEMPLATE_ATTR_PREFIX)) {
|
|
29558
|
+
invalid = true;
|
|
29559
|
+
this.reportError(`Shorthand template syntax "${attr.name}" is not supported inside a directive context`, attr.sourceSpan);
|
|
29560
|
+
}
|
|
29561
|
+
else if (UNSUPPORTED_SELECTORLESS_DIRECTIVE_ATTRS.has(attr.name)) {
|
|
29562
|
+
invalid = true;
|
|
29563
|
+
this.reportError(`Attribute "${attr.name}" is not supported in a directive context`, attr.sourceSpan);
|
|
29564
|
+
}
|
|
29565
|
+
}
|
|
29566
|
+
if (!invalid && seenDirectives.has(directive.name)) {
|
|
29567
|
+
invalid = true;
|
|
29568
|
+
this.reportError(`Cannot apply directive "${directive.name}" multiple times on the same element`, directive.sourceSpan);
|
|
29569
|
+
}
|
|
29570
|
+
if (invalid) {
|
|
29571
|
+
continue;
|
|
29572
|
+
}
|
|
29573
|
+
const { attributes, parsedProperties, boundEvents, references, i18nAttrsMeta } = this.prepareAttributes(directive.attrs, false);
|
|
29574
|
+
const { bound: inputs } = this.categorizePropertyAttributes(elementName, parsedProperties, i18nAttrsMeta);
|
|
29575
|
+
for (const input of inputs) {
|
|
29576
|
+
if (input.type !== BindingType.Property && input.type !== BindingType.TwoWay) {
|
|
29577
|
+
invalid = true;
|
|
29578
|
+
this.reportError('Binding is not supported in a directive context', input.sourceSpan);
|
|
29579
|
+
}
|
|
29580
|
+
}
|
|
29581
|
+
if (invalid) {
|
|
29582
|
+
continue;
|
|
29583
|
+
}
|
|
29584
|
+
seenDirectives.add(directive.name);
|
|
29585
|
+
directives.push(new Directive$1(directive.name, attributes, inputs, boundEvents, references, directive.sourceSpan, directive.startSourceSpan, directive.endSourceSpan, undefined));
|
|
29586
|
+
}
|
|
29587
|
+
return directives;
|
|
29588
|
+
}
|
|
29589
|
+
wrapInTemplate(node, templateProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement) {
|
|
29590
|
+
// We need to hoist the attributes of the node to the template for content projection purposes.
|
|
29591
|
+
const attrs = this.categorizePropertyAttributes('ng-template', templateProperties, i18nAttrsMeta);
|
|
29592
|
+
const templateAttrs = [];
|
|
29593
|
+
attrs.literal.forEach((attr) => templateAttrs.push(attr));
|
|
29594
|
+
attrs.bound.forEach((attr) => templateAttrs.push(attr));
|
|
29595
|
+
const hoistedAttrs = {
|
|
29596
|
+
attributes: [],
|
|
29597
|
+
inputs: [],
|
|
29598
|
+
outputs: [],
|
|
29599
|
+
};
|
|
29600
|
+
if (node instanceof Element$1 || node instanceof Component$1) {
|
|
29601
|
+
hoistedAttrs.attributes.push(...node.attributes);
|
|
29602
|
+
hoistedAttrs.inputs.push(...node.inputs);
|
|
29603
|
+
hoistedAttrs.outputs.push(...node.outputs);
|
|
29604
|
+
}
|
|
29605
|
+
// For <ng-template>s with structural directives on them, avoid passing i18n information to
|
|
29606
|
+
// the wrapping template to prevent unnecessary i18n instructions from being generated. The
|
|
29607
|
+
// necessary i18n meta information will be extracted from child elements.
|
|
29608
|
+
const i18n = isTemplateElement && isI18nRootElement ? undefined : node.i18n;
|
|
29609
|
+
let name;
|
|
29610
|
+
if (node instanceof Component$1) {
|
|
29611
|
+
name = node.tagName;
|
|
29612
|
+
}
|
|
29613
|
+
else if (node instanceof Template) {
|
|
29614
|
+
name = null;
|
|
29615
|
+
}
|
|
29616
|
+
else {
|
|
29617
|
+
name = node.name;
|
|
29618
|
+
}
|
|
29619
|
+
return new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, [
|
|
29620
|
+
// Do not copy over the directives.
|
|
29621
|
+
], templateAttrs, [node], [
|
|
29622
|
+
// Do not copy over the references.
|
|
29623
|
+
], templateVariables, node.sourceSpan, node.startSourceSpan, node.endSourceSpan, i18n);
|
|
29624
|
+
}
|
|
29003
29625
|
_visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) {
|
|
29004
29626
|
const valueNoNgsp = replaceNgsp(value);
|
|
29005
29627
|
const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens);
|
|
@@ -29050,7 +29672,8 @@ class NonBindableVisitor {
|
|
|
29050
29672
|
const children = visitAll(this, ast.children, null);
|
|
29051
29673
|
return new Element$1(ast.name, visitAll(this, ast.attrs),
|
|
29052
29674
|
/* inputs */ [],
|
|
29053
|
-
/* outputs */ [],
|
|
29675
|
+
/* outputs */ [],
|
|
29676
|
+
/* directives */ [], children,
|
|
29054
29677
|
/* references */ [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
29055
29678
|
}
|
|
29056
29679
|
visitComment(comment) {
|
|
@@ -29086,6 +29709,17 @@ class NonBindableVisitor {
|
|
|
29086
29709
|
visitLetDeclaration(decl, context) {
|
|
29087
29710
|
return new Text$3(`@let ${decl.name} = ${decl.value};`, decl.sourceSpan);
|
|
29088
29711
|
}
|
|
29712
|
+
visitComponent(ast, context) {
|
|
29713
|
+
const children = visitAll(this, ast.children, null);
|
|
29714
|
+
return new Element$1(ast.fullName, visitAll(this, ast.attrs),
|
|
29715
|
+
/* inputs */ [],
|
|
29716
|
+
/* outputs */ [],
|
|
29717
|
+
/* directives */ [], children,
|
|
29718
|
+
/* references */ [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
|
|
29719
|
+
}
|
|
29720
|
+
visitDirective(directive, context) {
|
|
29721
|
+
return null;
|
|
29722
|
+
}
|
|
29089
29723
|
}
|
|
29090
29724
|
const NON_BINDABLE_VISITOR = new NonBindableVisitor();
|
|
29091
29725
|
function normalizeAttributeName(attrName) {
|
|
@@ -29942,6 +30576,7 @@ class Scope {
|
|
|
29942
30576
|
}
|
|
29943
30577
|
}
|
|
29944
30578
|
visitElement(element) {
|
|
30579
|
+
element.directives.forEach((node) => node.visit(this));
|
|
29945
30580
|
// `Element`s in the template may have `Reference`s which are captured in the scope.
|
|
29946
30581
|
element.references.forEach((node) => this.visitReference(node));
|
|
29947
30582
|
// Recurse into the `Element`'s children.
|
|
@@ -29949,6 +30584,7 @@ class Scope {
|
|
|
29949
30584
|
this.elementsInScope.add(element);
|
|
29950
30585
|
}
|
|
29951
30586
|
visitTemplate(template) {
|
|
30587
|
+
template.directives.forEach((node) => node.visit(this));
|
|
29952
30588
|
// References on a <ng-template> are defined in the outer scope, so capture them before
|
|
29953
30589
|
// processing the template's child scope.
|
|
29954
30590
|
template.references.forEach((node) => this.visitReference(node));
|
|
@@ -30003,6 +30639,12 @@ class Scope {
|
|
|
30003
30639
|
visitLetDeclaration(decl) {
|
|
30004
30640
|
this.maybeDeclare(decl);
|
|
30005
30641
|
}
|
|
30642
|
+
visitComponent(component) {
|
|
30643
|
+
throw new Error('TODO');
|
|
30644
|
+
}
|
|
30645
|
+
visitDirective(directive) {
|
|
30646
|
+
throw new Error('TODO');
|
|
30647
|
+
}
|
|
30006
30648
|
// Unused visitors.
|
|
30007
30649
|
visitBoundAttribute(attr) { }
|
|
30008
30650
|
visitBoundEvent(event) { }
|
|
@@ -30104,6 +30746,10 @@ class DirectiveBinder {
|
|
|
30104
30746
|
// First, determine the HTML shape of the node for the purpose of directive matching.
|
|
30105
30747
|
// Do this by building up a `CssSelector` for the node.
|
|
30106
30748
|
const cssSelector = createCssSelectorFromNode(node);
|
|
30749
|
+
// TODO(crisbeto): account for selectorless directives here.
|
|
30750
|
+
if (node.directives.length > 0) {
|
|
30751
|
+
throw new Error('TODO');
|
|
30752
|
+
}
|
|
30107
30753
|
// Next, use the `SelectorMatcher` to get the list of directives on the node.
|
|
30108
30754
|
const directives = [];
|
|
30109
30755
|
this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
|
|
@@ -30203,6 +30849,12 @@ class DirectiveBinder {
|
|
|
30203
30849
|
visitContent(content) {
|
|
30204
30850
|
content.children.forEach((child) => child.visit(this));
|
|
30205
30851
|
}
|
|
30852
|
+
visitComponent(component) {
|
|
30853
|
+
throw new Error('TODO');
|
|
30854
|
+
}
|
|
30855
|
+
visitDirective(directive) {
|
|
30856
|
+
throw new Error('TODO');
|
|
30857
|
+
}
|
|
30206
30858
|
// Unused visitors.
|
|
30207
30859
|
visitVariable(variable) { }
|
|
30208
30860
|
visitReference(reference) { }
|
|
@@ -30333,6 +30985,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
30333
30985
|
// Visit the inputs, outputs, and children of the element.
|
|
30334
30986
|
element.inputs.forEach(this.visitNode);
|
|
30335
30987
|
element.outputs.forEach(this.visitNode);
|
|
30988
|
+
element.directives.forEach(this.visitNode);
|
|
30336
30989
|
element.children.forEach(this.visitNode);
|
|
30337
30990
|
element.references.forEach(this.visitNode);
|
|
30338
30991
|
}
|
|
@@ -30340,6 +30993,7 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
30340
30993
|
// First, visit inputs, outputs and template attributes of the template node.
|
|
30341
30994
|
template.inputs.forEach(this.visitNode);
|
|
30342
30995
|
template.outputs.forEach(this.visitNode);
|
|
30996
|
+
template.directives.forEach(this.visitNode);
|
|
30343
30997
|
template.templateAttrs.forEach(this.visitNode);
|
|
30344
30998
|
template.references.forEach(this.visitNode);
|
|
30345
30999
|
// Next, recurse into the template.
|
|
@@ -30357,6 +31011,12 @@ class TemplateBinder extends RecursiveAstVisitor {
|
|
|
30357
31011
|
this.symbols.set(reference, this.rootNode);
|
|
30358
31012
|
}
|
|
30359
31013
|
}
|
|
31014
|
+
visitComponent(component) {
|
|
31015
|
+
throw new Error('TODO');
|
|
31016
|
+
}
|
|
31017
|
+
visitDirective(directive) {
|
|
31018
|
+
throw new Error('TODO');
|
|
31019
|
+
}
|
|
30360
31020
|
// Unused template visitors
|
|
30361
31021
|
visitText(text) { }
|
|
30362
31022
|
visitTextAttribute(attribute) { }
|
|
@@ -31425,7 +32085,7 @@ class _Visitor {
|
|
|
31425
32085
|
this._init(_VisitorMode.Merge, interpolationConfig);
|
|
31426
32086
|
this._translations = translations;
|
|
31427
32087
|
// Construct a single fake root element
|
|
31428
|
-
const wrapper = new Element('wrapper', [], nodes, undefined, undefined, undefined);
|
|
32088
|
+
const wrapper = new Element('wrapper', [], [], nodes, undefined, undefined, undefined);
|
|
31429
32089
|
const translatedNode = wrapper.visit(this, null);
|
|
31430
32090
|
if (this._inI18nBlock) {
|
|
31431
32091
|
this._reportError(nodes[nodes.length - 1], 'Unclosed block');
|
|
@@ -31511,7 +32171,41 @@ class _Visitor {
|
|
|
31511
32171
|
return text;
|
|
31512
32172
|
}
|
|
31513
32173
|
visitElement(el, context) {
|
|
31514
|
-
this.
|
|
32174
|
+
return this._visitElementLike(el, context);
|
|
32175
|
+
}
|
|
32176
|
+
visitAttribute(attribute, context) {
|
|
32177
|
+
throw new Error('unreachable code');
|
|
32178
|
+
}
|
|
32179
|
+
visitBlock(block, context) {
|
|
32180
|
+
visitAll(this, block.children, context);
|
|
32181
|
+
}
|
|
32182
|
+
visitBlockParameter(parameter, context) { }
|
|
32183
|
+
visitLetDeclaration(decl, context) { }
|
|
32184
|
+
visitComponent(component, context) {
|
|
32185
|
+
return this._visitElementLike(component, context);
|
|
32186
|
+
}
|
|
32187
|
+
visitDirective(directive, context) {
|
|
32188
|
+
throw new Error('unreachable code');
|
|
32189
|
+
}
|
|
32190
|
+
_init(mode, interpolationConfig) {
|
|
32191
|
+
this._mode = mode;
|
|
32192
|
+
this._inI18nBlock = false;
|
|
32193
|
+
this._inI18nNode = false;
|
|
32194
|
+
this._depth = 0;
|
|
32195
|
+
this._inIcu = false;
|
|
32196
|
+
this._msgCountAtSectionStart = undefined;
|
|
32197
|
+
this._errors = [];
|
|
32198
|
+
this._messages = [];
|
|
32199
|
+
this._inImplicitNode = false;
|
|
32200
|
+
this._createI18nMessage = createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS,
|
|
32201
|
+
// When dropping significant whitespace we need to retain whitespace tokens or
|
|
32202
|
+
// else we won't be able to reuse source spans because empty tokens would be
|
|
32203
|
+
// removed and cause a mismatch.
|
|
32204
|
+
/* retainEmptyTokens */ !this._preserveSignificantWhitespace,
|
|
32205
|
+
/* preserveExpressionWhitespace */ this._preserveSignificantWhitespace);
|
|
32206
|
+
}
|
|
32207
|
+
_visitElementLike(node, context) {
|
|
32208
|
+
this._mayBeAddBlockChildren(node);
|
|
31515
32209
|
this._depth++;
|
|
31516
32210
|
const wasInI18nNode = this._inI18nNode;
|
|
31517
32211
|
const wasInImplicitNode = this._inImplicitNode;
|
|
@@ -31520,9 +32214,10 @@ class _Visitor {
|
|
|
31520
32214
|
// Extract:
|
|
31521
32215
|
// - top level nodes with the (implicit) "i18n" attribute if not already in a section
|
|
31522
32216
|
// - ICU messages
|
|
31523
|
-
const
|
|
32217
|
+
const nodeName = node instanceof Component ? node.tagName : node.name;
|
|
32218
|
+
const i18nAttr = _getI18nAttr(node);
|
|
31524
32219
|
const i18nMeta = i18nAttr ? i18nAttr.value : '';
|
|
31525
|
-
const isImplicit = this._implicitTags.some((tag) =>
|
|
32220
|
+
const isImplicit = this._implicitTags.some((tag) => nodeName === tag) &&
|
|
31526
32221
|
!this._inIcu &&
|
|
31527
32222
|
!this._isInTranslatableSection;
|
|
31528
32223
|
const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
|
|
@@ -31530,29 +32225,29 @@ class _Visitor {
|
|
|
31530
32225
|
if (!this._isInTranslatableSection && !this._inIcu) {
|
|
31531
32226
|
if (i18nAttr || isTopLevelImplicit) {
|
|
31532
32227
|
this._inI18nNode = true;
|
|
31533
|
-
const message = this._addMessage(
|
|
31534
|
-
translatedChildNodes = this._translateMessage(
|
|
32228
|
+
const message = this._addMessage(node.children, i18nMeta);
|
|
32229
|
+
translatedChildNodes = this._translateMessage(node, message);
|
|
31535
32230
|
}
|
|
31536
32231
|
if (this._mode == _VisitorMode.Extract) {
|
|
31537
32232
|
const isTranslatable = i18nAttr || isTopLevelImplicit;
|
|
31538
32233
|
if (isTranslatable)
|
|
31539
|
-
this._openTranslatableSection(
|
|
31540
|
-
visitAll(this,
|
|
32234
|
+
this._openTranslatableSection(node);
|
|
32235
|
+
visitAll(this, node.children);
|
|
31541
32236
|
if (isTranslatable)
|
|
31542
|
-
this._closeTranslatableSection(
|
|
32237
|
+
this._closeTranslatableSection(node, node.children);
|
|
31543
32238
|
}
|
|
31544
32239
|
}
|
|
31545
32240
|
else {
|
|
31546
32241
|
if (i18nAttr || isTopLevelImplicit) {
|
|
31547
|
-
this._reportError(
|
|
32242
|
+
this._reportError(node, 'Could not mark an element as translatable inside a translatable section');
|
|
31548
32243
|
}
|
|
31549
32244
|
if (this._mode == _VisitorMode.Extract) {
|
|
31550
32245
|
// Descend into child nodes for extraction
|
|
31551
|
-
visitAll(this,
|
|
32246
|
+
visitAll(this, node.children);
|
|
31552
32247
|
}
|
|
31553
32248
|
}
|
|
31554
32249
|
if (this._mode === _VisitorMode.Merge) {
|
|
31555
|
-
const visitNodes = translatedChildNodes ||
|
|
32250
|
+
const visitNodes = translatedChildNodes || node.children;
|
|
31556
32251
|
visitNodes.forEach((child) => {
|
|
31557
32252
|
const visited = child.visit(this, context);
|
|
31558
32253
|
if (visited && !this._isInTranslatableSection) {
|
|
@@ -31562,48 +32257,29 @@ class _Visitor {
|
|
|
31562
32257
|
}
|
|
31563
32258
|
});
|
|
31564
32259
|
}
|
|
31565
|
-
this._visitAttributesOf(
|
|
32260
|
+
this._visitAttributesOf(node);
|
|
31566
32261
|
this._depth--;
|
|
31567
32262
|
this._inI18nNode = wasInI18nNode;
|
|
31568
32263
|
this._inImplicitNode = wasInImplicitNode;
|
|
31569
32264
|
if (this._mode === _VisitorMode.Merge) {
|
|
31570
|
-
|
|
31571
|
-
|
|
32265
|
+
if (node instanceof Element) {
|
|
32266
|
+
return new Element(node.name, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
32267
|
+
}
|
|
32268
|
+
else {
|
|
32269
|
+
return new Component(node.componentName, node.tagName, node.fullName, this._translateAttributes(node), this._translateDirectives(node), childNodes, node.sourceSpan, node.startSourceSpan, node.endSourceSpan);
|
|
32270
|
+
}
|
|
31572
32271
|
}
|
|
31573
32272
|
return null;
|
|
31574
32273
|
}
|
|
31575
|
-
visitAttribute(attribute, context) {
|
|
31576
|
-
throw new Error('unreachable code');
|
|
31577
|
-
}
|
|
31578
|
-
visitBlock(block, context) {
|
|
31579
|
-
visitAll(this, block.children, context);
|
|
31580
|
-
}
|
|
31581
|
-
visitBlockParameter(parameter, context) { }
|
|
31582
|
-
visitLetDeclaration(decl, context) { }
|
|
31583
|
-
_init(mode, interpolationConfig) {
|
|
31584
|
-
this._mode = mode;
|
|
31585
|
-
this._inI18nBlock = false;
|
|
31586
|
-
this._inI18nNode = false;
|
|
31587
|
-
this._depth = 0;
|
|
31588
|
-
this._inIcu = false;
|
|
31589
|
-
this._msgCountAtSectionStart = undefined;
|
|
31590
|
-
this._errors = [];
|
|
31591
|
-
this._messages = [];
|
|
31592
|
-
this._inImplicitNode = false;
|
|
31593
|
-
this._createI18nMessage = createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS,
|
|
31594
|
-
// When dropping significant whitespace we need to retain whitespace tokens or
|
|
31595
|
-
// else we won't be able to reuse source spans because empty tokens would be
|
|
31596
|
-
// removed and cause a mismatch.
|
|
31597
|
-
/* retainEmptyTokens */ !this._preserveSignificantWhitespace,
|
|
31598
|
-
/* preserveExpressionWhitespace */ this._preserveSignificantWhitespace);
|
|
31599
|
-
}
|
|
31600
32274
|
// looks for translatable attributes
|
|
31601
32275
|
_visitAttributesOf(el) {
|
|
31602
32276
|
const explicitAttrNameToValue = {};
|
|
31603
|
-
const implicitAttrNames = this._implicitAttrs[el.name] || [];
|
|
32277
|
+
const implicitAttrNames = this._implicitAttrs[el instanceof Component ? el.tagName || '' : el.name] || [];
|
|
31604
32278
|
el.attrs
|
|
31605
|
-
.filter((attr) => attr.name.startsWith(_I18N_ATTR_PREFIX))
|
|
31606
|
-
.forEach((attr) =>
|
|
32279
|
+
.filter((attr) => attr instanceof Attribute && attr.name.startsWith(_I18N_ATTR_PREFIX))
|
|
32280
|
+
.forEach((attr) => {
|
|
32281
|
+
explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value;
|
|
32282
|
+
});
|
|
31607
32283
|
el.attrs.forEach((attr) => {
|
|
31608
32284
|
if (attr.name in explicitAttrNameToValue) {
|
|
31609
32285
|
this._addMessage([attr], explicitAttrNameToValue[attr.name]);
|
|
@@ -31676,16 +32352,15 @@ class _Visitor {
|
|
|
31676
32352
|
return [];
|
|
31677
32353
|
}
|
|
31678
32354
|
// translate the attributes of an element and remove i18n specific attributes
|
|
31679
|
-
_translateAttributes(
|
|
31680
|
-
const attributes = el.attrs;
|
|
32355
|
+
_translateAttributes(node) {
|
|
31681
32356
|
const i18nParsedMessageMeta = {};
|
|
31682
|
-
|
|
32357
|
+
const translatedAttributes = [];
|
|
32358
|
+
node.attrs.forEach((attr) => {
|
|
31683
32359
|
if (attr.name.startsWith(_I18N_ATTR_PREFIX)) {
|
|
31684
32360
|
i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value);
|
|
31685
32361
|
}
|
|
31686
32362
|
});
|
|
31687
|
-
|
|
31688
|
-
attributes.forEach((attr) => {
|
|
32363
|
+
node.attrs.forEach((attr) => {
|
|
31689
32364
|
if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) {
|
|
31690
32365
|
// strip i18n specific attributes
|
|
31691
32366
|
return;
|
|
@@ -31703,11 +32378,11 @@ class _Visitor {
|
|
|
31703
32378
|
translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */));
|
|
31704
32379
|
}
|
|
31705
32380
|
else {
|
|
31706
|
-
this._reportError(
|
|
32381
|
+
this._reportError(node, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
|
|
31707
32382
|
}
|
|
31708
32383
|
}
|
|
31709
32384
|
else {
|
|
31710
|
-
this._reportError(
|
|
32385
|
+
this._reportError(node, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
|
|
31711
32386
|
}
|
|
31712
32387
|
}
|
|
31713
32388
|
else {
|
|
@@ -31716,6 +32391,9 @@ class _Visitor {
|
|
|
31716
32391
|
});
|
|
31717
32392
|
return translatedAttributes;
|
|
31718
32393
|
}
|
|
32394
|
+
_translateDirectives(node) {
|
|
32395
|
+
return node.directives.map((dir) => new Directive(dir.name, this._translateAttributes(dir), dir.sourceSpan, dir.startSourceSpan, dir.endSourceSpan));
|
|
32396
|
+
}
|
|
31719
32397
|
/**
|
|
31720
32398
|
* Add the node as a child of the block when:
|
|
31721
32399
|
* - we are in a block,
|
|
@@ -31791,7 +32469,7 @@ function _isClosingComment(n) {
|
|
|
31791
32469
|
return !!(n instanceof Comment && n.value && n.value === '/i18n');
|
|
31792
32470
|
}
|
|
31793
32471
|
function _getI18nAttr(p) {
|
|
31794
|
-
return p.attrs.find((attr) => attr.name === _I18N_ATTR) || null;
|
|
32472
|
+
return (p.attrs.find((attr) => attr instanceof Attribute && attr.name === _I18N_ATTR) || null);
|
|
31795
32473
|
}
|
|
31796
32474
|
function _parseMessageMeta(i18n) {
|
|
31797
32475
|
if (!i18n)
|
|
@@ -31839,7 +32517,12 @@ class XmlParser extends Parser$1 {
|
|
|
31839
32517
|
}
|
|
31840
32518
|
parse(source, url, options = {}) {
|
|
31841
32519
|
// Blocks and let declarations aren't supported in an XML context.
|
|
31842
|
-
return super.parse(source, url, {
|
|
32520
|
+
return super.parse(source, url, {
|
|
32521
|
+
...options,
|
|
32522
|
+
tokenizeBlocks: false,
|
|
32523
|
+
tokenizeLet: false,
|
|
32524
|
+
selectorlessEnabled: false,
|
|
32525
|
+
});
|
|
31843
32526
|
}
|
|
31844
32527
|
}
|
|
31845
32528
|
|
|
@@ -32063,6 +32746,8 @@ class XliffParser {
|
|
|
32063
32746
|
visitBlock(block, context) { }
|
|
32064
32747
|
visitBlockParameter(parameter, context) { }
|
|
32065
32748
|
visitLetDeclaration(decl, context) { }
|
|
32749
|
+
visitComponent(component, context) { }
|
|
32750
|
+
visitDirective(directive, context) { }
|
|
32066
32751
|
_addError(node, message) {
|
|
32067
32752
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32068
32753
|
}
|
|
@@ -32118,6 +32803,12 @@ let XmlToI18n$2 = class XmlToI18n {
|
|
|
32118
32803
|
visitBlock(block, context) { }
|
|
32119
32804
|
visitBlockParameter(parameter, context) { }
|
|
32120
32805
|
visitLetDeclaration(decl, context) { }
|
|
32806
|
+
visitComponent(component, context) {
|
|
32807
|
+
this._addError(component, 'Unexpected node');
|
|
32808
|
+
}
|
|
32809
|
+
visitDirective(directive, context) {
|
|
32810
|
+
this._addError(directive, 'Unexpected node');
|
|
32811
|
+
}
|
|
32121
32812
|
_addError(node, message) {
|
|
32122
32813
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32123
32814
|
}
|
|
@@ -32378,6 +33069,8 @@ class Xliff2Parser {
|
|
|
32378
33069
|
visitBlock(block, context) { }
|
|
32379
33070
|
visitBlockParameter(parameter, context) { }
|
|
32380
33071
|
visitLetDeclaration(decl, context) { }
|
|
33072
|
+
visitComponent(component, context) { }
|
|
33073
|
+
visitDirective(directive, context) { }
|
|
32381
33074
|
_addError(node, message) {
|
|
32382
33075
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32383
33076
|
}
|
|
@@ -32450,6 +33143,12 @@ let XmlToI18n$1 = class XmlToI18n {
|
|
|
32450
33143
|
visitBlock(block, context) { }
|
|
32451
33144
|
visitBlockParameter(parameter, context) { }
|
|
32452
33145
|
visitLetDeclaration(decl, context) { }
|
|
33146
|
+
visitComponent(component, context) {
|
|
33147
|
+
this._addError(component, 'Unexpected node');
|
|
33148
|
+
}
|
|
33149
|
+
visitDirective(directive, context) {
|
|
33150
|
+
this._addError(directive, 'Unexpected node');
|
|
33151
|
+
}
|
|
32453
33152
|
_addError(node, message) {
|
|
32454
33153
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32455
33154
|
}
|
|
@@ -32589,6 +33288,12 @@ class XtbParser {
|
|
|
32589
33288
|
visitBlock(block, context) { }
|
|
32590
33289
|
visitBlockParameter(block, context) { }
|
|
32591
33290
|
visitLetDeclaration(decl, context) { }
|
|
33291
|
+
visitComponent(component, context) {
|
|
33292
|
+
this._addError(component, 'Unexpected node');
|
|
33293
|
+
}
|
|
33294
|
+
visitDirective(directive, context) {
|
|
33295
|
+
this._addError(directive, 'Unexpected node');
|
|
33296
|
+
}
|
|
32592
33297
|
_addError(node, message) {
|
|
32593
33298
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32594
33299
|
}
|
|
@@ -32642,6 +33347,12 @@ class XmlToI18n {
|
|
|
32642
33347
|
visitBlock(block, context) { }
|
|
32643
33348
|
visitBlockParameter(block, context) { }
|
|
32644
33349
|
visitLetDeclaration(decl, context) { }
|
|
33350
|
+
visitComponent(component, context) {
|
|
33351
|
+
this._addError(component, 'Unexpected node');
|
|
33352
|
+
}
|
|
33353
|
+
visitDirective(directive, context) {
|
|
33354
|
+
this._addError(directive, 'Unexpected node');
|
|
33355
|
+
}
|
|
32645
33356
|
_addError(node, message) {
|
|
32646
33357
|
this._errors.push(new I18nError(node.sourceSpan, message));
|
|
32647
33358
|
}
|
|
@@ -33055,7 +33766,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
|
|
|
33055
33766
|
function compileDeclareClassMetadata(metadata) {
|
|
33056
33767
|
const definitionMap = new DefinitionMap();
|
|
33057
33768
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
|
|
33058
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
33769
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33059
33770
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33060
33771
|
definitionMap.set('type', metadata.type);
|
|
33061
33772
|
definitionMap.set('decorators', metadata.decorators);
|
|
@@ -33073,7 +33784,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
|
|
|
33073
33784
|
callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
|
|
33074
33785
|
callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
|
|
33075
33786
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
|
|
33076
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
33787
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33077
33788
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33078
33789
|
definitionMap.set('type', metadata.type);
|
|
33079
33790
|
definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
|
|
@@ -33168,7 +33879,7 @@ function createDirectiveDefinitionMap(meta) {
|
|
|
33168
33879
|
const definitionMap = new DefinitionMap();
|
|
33169
33880
|
const minVersion = getMinimumVersionForPartialOutput(meta);
|
|
33170
33881
|
definitionMap.set('minVersion', literal(minVersion));
|
|
33171
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
33882
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33172
33883
|
// e.g. `type: MyDirective`
|
|
33173
33884
|
definitionMap.set('type', meta.type.value);
|
|
33174
33885
|
if (meta.isStandalone !== undefined) {
|
|
@@ -33584,7 +34295,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
|
|
|
33584
34295
|
function compileDeclareFactoryFunction(meta) {
|
|
33585
34296
|
const definitionMap = new DefinitionMap();
|
|
33586
34297
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
|
|
33587
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
34298
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33588
34299
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33589
34300
|
definitionMap.set('type', meta.type.value);
|
|
33590
34301
|
definitionMap.set('deps', compileDependencies(meta.deps));
|
|
@@ -33619,7 +34330,7 @@ function compileDeclareInjectableFromMetadata(meta) {
|
|
|
33619
34330
|
function createInjectableDefinitionMap(meta) {
|
|
33620
34331
|
const definitionMap = new DefinitionMap();
|
|
33621
34332
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
|
|
33622
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
34333
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33623
34334
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33624
34335
|
definitionMap.set('type', meta.type.value);
|
|
33625
34336
|
// Only generate providedIn property if it has a non-null value
|
|
@@ -33670,7 +34381,7 @@ function compileDeclareInjectorFromMetadata(meta) {
|
|
|
33670
34381
|
function createInjectorDefinitionMap(meta) {
|
|
33671
34382
|
const definitionMap = new DefinitionMap();
|
|
33672
34383
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
|
|
33673
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
34384
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33674
34385
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33675
34386
|
definitionMap.set('type', meta.type.value);
|
|
33676
34387
|
definitionMap.set('providers', meta.providers);
|
|
@@ -33703,7 +34414,7 @@ function createNgModuleDefinitionMap(meta) {
|
|
|
33703
34414
|
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
|
|
33704
34415
|
}
|
|
33705
34416
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
|
|
33706
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
34417
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33707
34418
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33708
34419
|
definitionMap.set('type', meta.type.value);
|
|
33709
34420
|
// We only generate the keys in the metadata if the arrays contain values.
|
|
@@ -33754,7 +34465,7 @@ function compileDeclarePipeFromMetadata(meta) {
|
|
|
33754
34465
|
function createPipeDefinitionMap(meta) {
|
|
33755
34466
|
const definitionMap = new DefinitionMap();
|
|
33756
34467
|
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
|
|
33757
|
-
definitionMap.set('version', literal('20.0.0-next.
|
|
34468
|
+
definitionMap.set('version', literal('20.0.0-next.6'));
|
|
33758
34469
|
definitionMap.set('ngImport', importExpr(Identifiers.core));
|
|
33759
34470
|
// e.g. `type: MyPipe`
|
|
33760
34471
|
definitionMap.set('type', meta.type.value);
|
|
@@ -33912,7 +34623,7 @@ function compileHmrUpdateCallback(definitions, constantStatements, meta) {
|
|
|
33912
34623
|
* @description
|
|
33913
34624
|
* Entry point for all public APIs of the compiler package.
|
|
33914
34625
|
*/
|
|
33915
|
-
const VERSION = new Version('20.0.0-next.
|
|
34626
|
+
const VERSION = new Version('20.0.0-next.6');
|
|
33916
34627
|
|
|
33917
34628
|
//////////////////////////////////////
|
|
33918
34629
|
// THIS FILE HAS GLOBAL SIDE EFFECT //
|
|
@@ -33938,5 +34649,5 @@ const VERSION = new Version('20.0.0-next.4');
|
|
|
33938
34649
|
// the late binding of the Compiler to the @angular/core for jit compilation.
|
|
33939
34650
|
publishFacade(_global);
|
|
33940
34651
|
|
|
33941
|
-
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BindingType, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, LetDeclaration, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParenthesizedExpr, ParenthesizedExpression, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, StringToken, StringTokenKind, TagContentType, TaggedTemplateLiteral, TaggedTemplateLiteralExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, TemplateLiteralElementExpr, TemplateLiteralExpr, Text, ThisReceiver, BlockNode as TmplAstBlockNode, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HostElement as TmplAstHostElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, LetDeclaration$1 as TmplAstLetDeclaration, NeverDeferredTrigger as TmplAstNeverDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, TypeofExpression, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, VoidExpr, VoidExpression, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDeferResolverFunction, compileDirectiveFromMetadata, compileFactoryFunction, compileHmrInitializer, compileHmrUpdateCallback, compileInjectable, compileInjector, compileNgModule, compileOpaqueAsyncClassMetadata, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, encapsulateStyle, findMatchingDirectivesAndPipes, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, visitAll$1 as tmplAstVisitAll, verifyHostBindings, visitAll };
|
|
34652
|
+
export { AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, ArrayType, ArrowFunctionExpr, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BindingType, Block, BlockParameter, BoundElementProperty, BuiltinType, BuiltinTypeName, CUSTOM_ELEMENTS_SCHEMA, Call, Chain, ChangeDetectionStrategy, CommaExpr, Comment, CompilerConfig, Component, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, Directive, DomElementSchemaRegistry, DynamicImportExpr, EOF, Element, ElementSchemaRegistry, EmitterVisitorContext, EmptyExpr$1 as EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, FactoryTarget$1 as FactoryTarget, FunctionExpr, HtmlParser, HtmlTagDefinition, I18NHtmlParser, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation$1 as Interpolation, InterpolationConfig, InvokeFunctionExpr, JSDocComment, JitEvaluator, KeyedRead, KeyedWrite, LeadingComment, LetDeclaration, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, LocalizedString, MapType, MessageBundle, NONE_TYPE, NO_ERRORS_SCHEMA, NodeWithI18n, NonNullAssert, NotExpr, ParenthesizedExpr, ParenthesizedExpression, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, ParserError, PrefixNot, PropertyRead, PropertyWrite, Identifiers as R3Identifiers, R3NgModuleMetadataKind, R3SelectorScopeMode, R3TargetBinder, R3TemplateDependencyKind, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveVisitor, ResourceLoader, ReturnStatement, STRING_TYPE, SafeCall, SafeKeyedRead, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StmtModifier, StringToken, StringTokenKind, TagContentType, TaggedTemplateLiteral, TaggedTemplateLiteralExpr, TemplateBindingParseResult, TemplateLiteral, TemplateLiteralElement, TemplateLiteralElementExpr, TemplateLiteralExpr, Text, ThisReceiver, BlockNode as TmplAstBlockNode, BoundAttribute as TmplAstBoundAttribute, BoundDeferredTrigger as TmplAstBoundDeferredTrigger, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Component$1 as TmplAstComponent, Content as TmplAstContent, DeferredBlock as TmplAstDeferredBlock, DeferredBlockError as TmplAstDeferredBlockError, DeferredBlockLoading as TmplAstDeferredBlockLoading, DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder, DeferredTrigger as TmplAstDeferredTrigger, Directive$1 as TmplAstDirective, Element$1 as TmplAstElement, ForLoopBlock as TmplAstForLoopBlock, ForLoopBlockEmpty as TmplAstForLoopBlockEmpty, HostElement as TmplAstHostElement, HoverDeferredTrigger as TmplAstHoverDeferredTrigger, Icu$1 as TmplAstIcu, IdleDeferredTrigger as TmplAstIdleDeferredTrigger, IfBlock as TmplAstIfBlock, IfBlockBranch as TmplAstIfBlockBranch, ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger, InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger, LetDeclaration$1 as TmplAstLetDeclaration, NeverDeferredTrigger as TmplAstNeverDeferredTrigger, RecursiveVisitor$1 as TmplAstRecursiveVisitor, Reference as TmplAstReference, SwitchBlock as TmplAstSwitchBlock, SwitchBlockCase as TmplAstSwitchBlockCase, Template as TmplAstTemplate, Text$3 as TmplAstText, TextAttribute as TmplAstTextAttribute, TimerDeferredTrigger as TmplAstTimerDeferredTrigger, UnknownBlock as TmplAstUnknownBlock, Variable as TmplAstVariable, ViewportDeferredTrigger as TmplAstViewportDeferredTrigger, Token, TokenType, TransplantedType, TreeError, Type, TypeModifier, TypeofExpr, TypeofExpression, Unary, UnaryOperator, UnaryOperatorExpr, VERSION, VariableBinding, Version, ViewEncapsulation, VoidExpr, VoidExpression, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, compileClassDebugInfo, compileClassMetadata, compileComponentClassMetadata, compileComponentDeclareClassMetadata, compileComponentFromMetadata, compileDeclareClassMetadata, compileDeclareComponentFromMetadata, compileDeclareDirectiveFromMetadata, compileDeclareFactoryFunction, compileDeclareInjectableFromMetadata, compileDeclareInjectorFromMetadata, compileDeclareNgModuleFromMetadata, compileDeclarePipeFromMetadata, compileDeferResolverFunction, compileDirectiveFromMetadata, compileFactoryFunction, compileHmrInitializer, compileHmrUpdateCallback, compileInjectable, compileInjector, compileNgModule, compileOpaqueAsyncClassMetadata, compilePipeFromMetadata, computeMsgId, core, createCssSelectorFromNode, createInjectableType, createMayBeForwardRefExpression, devOnlyGuardedExpression, emitDistinctChangesOnlyDefaultValue, encapsulateStyle, findMatchingDirectivesAndPipes, getHtmlTagDefinition, getNsPrefix, getSafePropertyAccessString, identifierName, isNgContainer, isNgContent, isNgTemplate, jsDocComment, leadingComment, literal, literalMap, makeBindingParser, mergeNsAndName, output_ast as outputAst, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, sanitizeIdentifier, splitNsName, visitAll$1 as tmplAstVisitAll, verifyHostBindings, visitAll };
|
|
33942
34653
|
//# sourceMappingURL=compiler.mjs.map
|