@angular/compiler 20.0.0-next.5 → 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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v20.0.0-next.5
2
+ * @license Angular v20.0.0-next.6
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -5068,17 +5068,19 @@ let Element$1 = class Element {
5068
5068
  attributes;
5069
5069
  inputs;
5070
5070
  outputs;
5071
+ directives;
5071
5072
  children;
5072
5073
  references;
5073
5074
  sourceSpan;
5074
5075
  startSourceSpan;
5075
5076
  endSourceSpan;
5076
5077
  i18n;
5077
- constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5078
+ constructor(name, attributes, inputs, outputs, directives, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5078
5079
  this.name = name;
5079
5080
  this.attributes = attributes;
5080
5081
  this.inputs = inputs;
5081
5082
  this.outputs = outputs;
5083
+ this.directives = directives;
5082
5084
  this.children = children;
5083
5085
  this.references = references;
5084
5086
  this.sourceSpan = sourceSpan;
@@ -5377,11 +5379,70 @@ let LetDeclaration$1 = class LetDeclaration {
5377
5379
  return visitor.visitLetDeclaration(this);
5378
5380
  }
5379
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
+ };
5380
5440
  class Template {
5381
5441
  tagName;
5382
5442
  attributes;
5383
5443
  inputs;
5384
5444
  outputs;
5445
+ directives;
5385
5446
  templateAttrs;
5386
5447
  children;
5387
5448
  references;
@@ -5395,11 +5456,12 @@ class Template {
5395
5456
  // `null` is a special case for when there is a structural directive on an `ng-template` so
5396
5457
  // the renderer can differentiate between the synthetic template and the one written in the
5397
5458
  // file.
5398
- 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) {
5399
5460
  this.tagName = tagName;
5400
5461
  this.attributes = attributes;
5401
5462
  this.inputs = inputs;
5402
5463
  this.outputs = outputs;
5464
+ this.directives = directives;
5403
5465
  this.templateAttrs = templateAttrs;
5404
5466
  this.children = children;
5405
5467
  this.references = references;
@@ -5418,13 +5480,17 @@ class Content {
5418
5480
  attributes;
5419
5481
  children;
5420
5482
  sourceSpan;
5483
+ startSourceSpan;
5484
+ endSourceSpan;
5421
5485
  i18n;
5422
5486
  name = 'ng-content';
5423
- constructor(selector, attributes, children, sourceSpan, i18n) {
5487
+ constructor(selector, attributes, children, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
5424
5488
  this.selector = selector;
5425
5489
  this.attributes = attributes;
5426
5490
  this.children = children;
5427
5491
  this.sourceSpan = sourceSpan;
5492
+ this.startSourceSpan = startSourceSpan;
5493
+ this.endSourceSpan = endSourceSpan;
5428
5494
  this.i18n = i18n;
5429
5495
  }
5430
5496
  visit(visitor) {
@@ -5507,6 +5573,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5507
5573
  visitAll$1(this, element.attributes);
5508
5574
  visitAll$1(this, element.inputs);
5509
5575
  visitAll$1(this, element.outputs);
5576
+ visitAll$1(this, element.directives);
5510
5577
  visitAll$1(this, element.children);
5511
5578
  visitAll$1(this, element.references);
5512
5579
  }
@@ -5514,6 +5581,7 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5514
5581
  visitAll$1(this, template.attributes);
5515
5582
  visitAll$1(this, template.inputs);
5516
5583
  visitAll$1(this, template.outputs);
5584
+ visitAll$1(this, template.directives);
5517
5585
  visitAll$1(this, template.children);
5518
5586
  visitAll$1(this, template.references);
5519
5587
  visitAll$1(this, template.variables);
@@ -5555,6 +5623,20 @@ let RecursiveVisitor$1 = class RecursiveVisitor {
5555
5623
  visitContent(content) {
5556
5624
  visitAll$1(this, content.children);
5557
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
+ }
5558
5640
  visitVariable(variable) { }
5559
5641
  visitReference(reference) { }
5560
5642
  visitTextAttribute(attribute) { }
@@ -6181,8 +6263,8 @@ const I18N_ICU_VAR_PREFIX = 'VAR_';
6181
6263
  function isI18nAttribute(name) {
6182
6264
  return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
6183
6265
  }
6184
- function hasI18nAttrs(element) {
6185
- return element.attrs.some((attr) => isI18nAttribute(attr.name));
6266
+ function hasI18nAttrs(node) {
6267
+ return node.attrs.some((attr) => isI18nAttribute(attr.name));
6186
6268
  }
6187
6269
  function icuFromI18nMessage(message) {
6188
6270
  return message.nodes[0];
@@ -13567,13 +13649,15 @@ class Attribute extends NodeWithI18n {
13567
13649
  class Element extends NodeWithI18n {
13568
13650
  name;
13569
13651
  attrs;
13652
+ directives;
13570
13653
  children;
13571
13654
  startSourceSpan;
13572
13655
  endSourceSpan;
13573
- constructor(name, attrs, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
13656
+ constructor(name, attrs, directives, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
13574
13657
  super(sourceSpan, i18n);
13575
13658
  this.name = name;
13576
13659
  this.attrs = attrs;
13660
+ this.directives = directives;
13577
13661
  this.children = children;
13578
13662
  this.startSourceSpan = startSourceSpan;
13579
13663
  this.endSourceSpan = endSourceSpan;
@@ -13613,6 +13697,47 @@ class Block extends NodeWithI18n {
13613
13697
  return visitor.visitBlock(this, context);
13614
13698
  }
13615
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
+ }
13616
13741
  class BlockParameter {
13617
13742
  expression;
13618
13743
  sourceSpan;
@@ -13659,6 +13784,7 @@ class RecursiveVisitor {
13659
13784
  visitElement(ast, context) {
13660
13785
  this.visitChildren(context, (visit) => {
13661
13786
  visit(ast.attrs);
13787
+ visit(ast.directives);
13662
13788
  visit(ast.children);
13663
13789
  });
13664
13790
  }
@@ -13679,6 +13805,17 @@ class RecursiveVisitor {
13679
13805
  }
13680
13806
  visitBlockParameter(ast, context) { }
13681
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
+ }
13682
13819
  visitChildren(context, cb) {
13683
13820
  let results = [];
13684
13821
  let t = this;
@@ -15882,11 +16019,13 @@ class _Tokenizer {
15882
16019
  _currentTokenStart = null;
15883
16020
  _currentTokenType = null;
15884
16021
  _expansionCaseStack = [];
16022
+ _openDirectiveCount = 0;
15885
16023
  _inInterpolation = false;
15886
16024
  _preserveLineEndings;
15887
16025
  _i18nNormalizeLineEndingsInICUs;
15888
16026
  _tokenizeBlocks;
15889
16027
  _tokenizeLet;
16028
+ _selectorlessEnabled;
15890
16029
  tokens = [];
15891
16030
  errors = [];
15892
16031
  nonNormalizedIcuExpressions = [];
@@ -15914,6 +16053,7 @@ class _Tokenizer {
15914
16053
  this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
15915
16054
  this._tokenizeBlocks = options.tokenizeBlocks ?? true;
15916
16055
  this._tokenizeLet = options.tokenizeLet ?? true;
16056
+ this._selectorlessEnabled = options.selectorlessEnabled ?? false;
15917
16057
  try {
15918
16058
  this._cursor.init();
15919
16059
  }
@@ -15982,7 +16122,7 @@ class _Tokenizer {
15982
16122
  this.handleError(e);
15983
16123
  }
15984
16124
  }
15985
- this._beginToken(33 /* TokenType.EOF */);
16125
+ this._beginToken(41 /* TokenType.EOF */);
15986
16126
  this._endToken([]);
15987
16127
  }
15988
16128
  _getBlockName() {
@@ -16381,7 +16521,7 @@ class _Tokenizer {
16381
16521
  this._cursor.advance();
16382
16522
  this._endToken([content]);
16383
16523
  }
16384
- _consumePrefixAndName() {
16524
+ _consumePrefixAndName(endPredicate) {
16385
16525
  const nameOrPrefixStart = this._cursor.clone();
16386
16526
  let prefix = '';
16387
16527
  while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
@@ -16396,41 +16536,64 @@ class _Tokenizer {
16396
16536
  else {
16397
16537
  nameStart = nameOrPrefixStart;
16398
16538
  }
16399
- this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
16539
+ this._requireCharCodeUntilFn(endPredicate, prefix === '' ? 0 : 1);
16400
16540
  const name = this._cursor.getChars(nameStart);
16401
16541
  return [prefix, name];
16402
16542
  }
16403
16543
  _consumeTagOpen(start) {
16404
16544
  let tagName;
16405
16545
  let prefix;
16406
- let openTagToken;
16546
+ let closingTagName;
16547
+ let openToken;
16407
16548
  try {
16408
- if (!isAsciiLetter(this._cursor.peek())) {
16409
- throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
16410
- }
16411
- openTagToken = this._consumeTagOpenStart(start);
16412
- prefix = openTagToken.parts[0];
16413
- tagName = openTagToken.parts[1];
16414
- this._attemptCharCodeUntilFn(isNotWhitespace);
16415
- while (this._cursor.peek() !== $SLASH &&
16416
- this._cursor.peek() !== $GT &&
16417
- this._cursor.peek() !== $LT &&
16418
- this._cursor.peek() !== $EOF) {
16419
- 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
+ }
16420
16558
  this._attemptCharCodeUntilFn(isNotWhitespace);
16421
- if (this._attemptCharCode($EQ)) {
16422
- this._attemptCharCodeUntilFn(isNotWhitespace);
16423
- this._consumeAttributeValue();
16559
+ }
16560
+ else {
16561
+ if (!isAsciiLetter(this._cursor.peek())) {
16562
+ throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
16424
16563
  }
16564
+ openToken = this._consumeTagOpenStart(start);
16565
+ prefix = openToken.parts[0];
16566
+ tagName = closingTagName = openToken.parts[1];
16425
16567
  this._attemptCharCodeUntilFn(isNotWhitespace);
16426
16568
  }
16427
- this._consumeTagOpenEnd();
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
+ }
16428
16588
  }
16429
16589
  catch (e) {
16430
16590
  if (e instanceof _ControlFlowError) {
16431
- if (openTagToken) {
16591
+ if (openToken) {
16432
16592
  // We errored before we could close the opening tag, so it is incomplete.
16433
- openTagToken.type = 4 /* TokenType.INCOMPLETE_TAG_OPEN */;
16593
+ openToken.type =
16594
+ openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
16595
+ ? 37 /* TokenType.INCOMPLETE_COMPONENT_OPEN */
16596
+ : 4 /* TokenType.INCOMPLETE_TAG_OPEN */;
16434
16597
  }
16435
16598
  else {
16436
16599
  // When the start tag is invalid, assume we want a "<" as text.
@@ -16444,13 +16607,13 @@ class _Tokenizer {
16444
16607
  }
16445
16608
  const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
16446
16609
  if (contentTokenType === TagContentType.RAW_TEXT) {
16447
- this._consumeRawTextWithTagClose(prefix, tagName, false);
16610
+ this._consumeRawTextWithTagClose(openToken, closingTagName, false);
16448
16611
  }
16449
16612
  else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
16450
- this._consumeRawTextWithTagClose(prefix, tagName, true);
16613
+ this._consumeRawTextWithTagClose(openToken, closingTagName, true);
16451
16614
  }
16452
16615
  }
16453
- _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) {
16616
+ _consumeRawTextWithTagClose(openToken, tagName, consumeEntities) {
16454
16617
  this._consumeRawText(consumeEntities, () => {
16455
16618
  if (!this._attemptCharCode($LT))
16456
16619
  return false;
@@ -16462,23 +16625,79 @@ class _Tokenizer {
16462
16625
  this._attemptCharCodeUntilFn(isNotWhitespace);
16463
16626
  return this._attemptCharCode($GT);
16464
16627
  });
16465
- this._beginToken(3 /* TokenType.TAG_CLOSE */);
16628
+ this._beginToken(openToken.type === 33 /* TokenType.COMPONENT_OPEN_START */
16629
+ ? 36 /* TokenType.COMPONENT_CLOSE */
16630
+ : 3 /* TokenType.TAG_CLOSE */);
16466
16631
  this._requireCharCodeUntilFn((code) => code === $GT, 3);
16467
16632
  this._cursor.advance(); // Consume the `>`
16468
- this._endToken([prefix, tagName]);
16633
+ this._endToken(openToken.parts);
16469
16634
  }
16470
16635
  _consumeTagOpenStart(start) {
16471
16636
  this._beginToken(0 /* TokenType.TAG_OPEN_START */, start);
16472
- const parts = this._consumePrefixAndName();
16637
+ const parts = this._consumePrefixAndName(isNameEnd);
16473
16638
  return this._endToken(parts);
16474
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
+ }
16475
16668
  _consumeAttributeName() {
16476
16669
  const attrNameStart = this._cursor.peek();
16477
16670
  if (attrNameStart === $SQ || attrNameStart === $DQ) {
16478
16671
  throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
16479
16672
  }
16480
16673
  this._beginToken(14 /* TokenType.ATTR_NAME */);
16481
- const prefixAndName = this._consumePrefixAndName();
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);
16482
16701
  this._endToken(prefixAndName);
16483
16702
  }
16484
16703
  _consumeAttributeValue() {
@@ -16509,10 +16728,32 @@ class _Tokenizer {
16509
16728
  this._requireCharCode($GT);
16510
16729
  this._endToken([]);
16511
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
+ }
16512
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
+ }
16513
16754
  this._beginToken(3 /* TokenType.TAG_CLOSE */, start);
16514
16755
  this._attemptCharCodeUntilFn(isNotWhitespace);
16515
- const prefixAndName = this._consumePrefixAndName();
16756
+ const prefixAndName = this._consumePrefixAndName(isNameEnd);
16516
16757
  this._attemptCharCodeUntilFn(isNotWhitespace);
16517
16758
  this._requireCharCode($GT);
16518
16759
  this._endToken(prefixAndName);
@@ -16668,6 +16909,50 @@ class _Tokenizer {
16668
16909
  parts.push(this._getProcessedChars(expressionStart, this._cursor));
16669
16910
  this._endToken(parts);
16670
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
+ }
16671
16956
  _getProcessedChars(start, end) {
16672
16957
  return this._processCarriageReturns(end.getChars(start));
16673
16958
  }
@@ -16783,6 +17068,15 @@ function isBlockNameChar(code) {
16783
17068
  function isBlockParameterChar(code) {
16784
17069
  return code !== $SEMICOLON && isNotWhitespace(code);
16785
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
+ }
16786
17080
  function mergeTextTokens(srcTokens) {
16787
17081
  const dstTokens = [];
16788
17082
  let lastDstToken = undefined;
@@ -17079,26 +17373,26 @@ let Parser$1 = class Parser {
17079
17373
  };
17080
17374
  class _TreeBuilder {
17081
17375
  tokens;
17082
- getTagDefinition;
17376
+ tagDefinitionResolver;
17083
17377
  _index = -1;
17084
17378
  // `_peek` will be initialized by the call to `_advance()` in the constructor.
17085
17379
  _peek;
17086
17380
  _containerStack = [];
17087
17381
  rootNodes = [];
17088
17382
  errors = [];
17089
- constructor(tokens, getTagDefinition) {
17383
+ constructor(tokens, tagDefinitionResolver) {
17090
17384
  this.tokens = tokens;
17091
- this.getTagDefinition = getTagDefinition;
17385
+ this.tagDefinitionResolver = tagDefinitionResolver;
17092
17386
  this._advance();
17093
17387
  }
17094
17388
  build() {
17095
- while (this._peek.type !== 33 /* TokenType.EOF */) {
17389
+ while (this._peek.type !== 41 /* TokenType.EOF */) {
17096
17390
  if (this._peek.type === 0 /* TokenType.TAG_OPEN_START */ ||
17097
17391
  this._peek.type === 4 /* TokenType.INCOMPLETE_TAG_OPEN */) {
17098
- this._consumeStartTag(this._advance());
17392
+ this._consumeElementStartTag(this._advance());
17099
17393
  }
17100
17394
  else if (this._peek.type === 3 /* TokenType.TAG_CLOSE */) {
17101
- this._consumeEndTag(this._advance());
17395
+ this._consumeElementEndTag(this._advance());
17102
17396
  }
17103
17397
  else if (this._peek.type === 12 /* TokenType.CDATA_START */) {
17104
17398
  this._closeVoidElement();
@@ -17137,6 +17431,13 @@ class _TreeBuilder {
17137
17431
  this._closeVoidElement();
17138
17432
  this._consumeIncompleteLet(this._advance());
17139
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
+ }
17140
17441
  else {
17141
17442
  // Skip all other tokens...
17142
17443
  this._advance();
@@ -17210,9 +17511,9 @@ class _TreeBuilder {
17210
17511
  if (!exp)
17211
17512
  return null;
17212
17513
  const end = this._advance();
17213
- exp.push({ type: 33 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
17514
+ exp.push({ type: 41 /* TokenType.EOF */, parts: [], sourceSpan: end.sourceSpan });
17214
17515
  // parse everything in between { and }
17215
- const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
17516
+ const expansionCaseParser = new _TreeBuilder(exp, this.tagDefinitionResolver);
17216
17517
  expansionCaseParser.build();
17217
17518
  if (expansionCaseParser.errors.length > 0) {
17218
17519
  this.errors = this.errors.concat(expansionCaseParser.errors);
@@ -17250,7 +17551,7 @@ class _TreeBuilder {
17250
17551
  return null;
17251
17552
  }
17252
17553
  }
17253
- if (this._peek.type === 33 /* TokenType.EOF */) {
17554
+ if (this._peek.type === 41 /* TokenType.EOF */) {
17254
17555
  this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
17255
17556
  return null;
17256
17557
  }
@@ -17265,7 +17566,7 @@ class _TreeBuilder {
17265
17566
  const parent = this._getContainer();
17266
17567
  if (parent != null &&
17267
17568
  parent.children.length === 0 &&
17268
- this.getTagDefinition(parent.name).ignoreFirstLf) {
17569
+ this._getTagDefinition(parent)?.ignoreFirstLf) {
17269
17570
  text = text.substring(1);
17270
17571
  tokens[0] = { type: token.type, sourceSpan: token.sourceSpan, parts: [text] };
17271
17572
  }
@@ -17296,25 +17597,23 @@ class _TreeBuilder {
17296
17597
  }
17297
17598
  _closeVoidElement() {
17298
17599
  const el = this._getContainer();
17299
- if (el instanceof Element && this.getTagDefinition(el.name).isVoid) {
17600
+ if (el !== null && this._getTagDefinition(el)?.isVoid) {
17300
17601
  this._containerStack.pop();
17301
17602
  }
17302
17603
  }
17303
- _consumeStartTag(startTagToken) {
17304
- const [prefix, name] = startTagToken.parts;
17604
+ _consumeElementStartTag(startTagToken) {
17305
17605
  const attrs = [];
17306
- while (this._peek.type === 14 /* TokenType.ATTR_NAME */) {
17307
- attrs.push(this._consumeAttr(this._advance()));
17308
- }
17309
- const fullName = this._getElementFullName(prefix, name, this._getClosestParentElement());
17606
+ const directives = [];
17607
+ this._consumeAttributesAndDirectives(attrs, directives);
17608
+ const fullName = this._getElementFullName(startTagToken, this._getClosestElementLikeParent());
17310
17609
  let selfClosing = false;
17311
17610
  // Note: There could have been a tokenizer error
17312
17611
  // so that we don't get a token for the end tag...
17313
17612
  if (this._peek.type === 2 /* TokenType.TAG_OPEN_END_VOID */) {
17314
17613
  this._advance();
17315
17614
  selfClosing = true;
17316
- const tagDef = this.getTagDefinition(fullName);
17317
- if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) {
17615
+ const tagDef = this._getTagDefinition(fullName);
17616
+ if (!(tagDef?.canSelfClose || getNsPrefix(fullName) !== null || tagDef?.isVoid)) {
17318
17617
  this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void, custom and foreign elements can be self closed "${startTagToken.parts[1]}"`));
17319
17618
  }
17320
17619
  }
@@ -17326,10 +17625,10 @@ class _TreeBuilder {
17326
17625
  const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
17327
17626
  // Create a separate `startSpan` because `span` will be modified when there is an `end` span.
17328
17627
  const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
17329
- const el = new Element(fullName, attrs, [], span, startSpan, undefined);
17330
- const parentEl = this._getContainer();
17331
- this._pushContainer(el, parentEl instanceof Element &&
17332
- this.getTagDefinition(parentEl.name).isClosedByChild(el.name));
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);
17333
17632
  if (selfClosing) {
17334
17633
  // Elements that are self-closed have their `endSourceSpan` set to the full span, as the
17335
17634
  // element start tag also represents the end tag.
@@ -17342,6 +17641,73 @@ class _TreeBuilder {
17342
17641
  this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
17343
17642
  }
17344
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
+ }
17345
17711
  _pushContainer(node, isClosedByChild) {
17346
17712
  if (isClosedByChild) {
17347
17713
  this._containerStack.pop();
@@ -17349,9 +17715,9 @@ class _TreeBuilder {
17349
17715
  this._addToParent(node);
17350
17716
  this._containerStack.push(node);
17351
17717
  }
17352
- _consumeEndTag(endTagToken) {
17353
- const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getClosestParentElement());
17354
- if (this.getTagDefinition(fullName).isVoid) {
17718
+ _consumeElementEndTag(endTagToken) {
17719
+ const fullName = this._getElementFullName(endTagToken, this._getClosestElementLikeParent());
17720
+ if (this._getTagDefinition(fullName)?.isVoid) {
17355
17721
  this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
17356
17722
  }
17357
17723
  else if (!this._popContainer(fullName, Element, endTagToken.sourceSpan)) {
@@ -17369,7 +17735,8 @@ class _TreeBuilder {
17369
17735
  let unexpectedCloseTagDetected = false;
17370
17736
  for (let stackIndex = this._containerStack.length - 1; stackIndex >= 0; stackIndex--) {
17371
17737
  const node = this._containerStack[stackIndex];
17372
- if ((node.name === expectedName || expectedName === null) && node instanceof expectedType) {
17738
+ const nodeName = node instanceof Component ? node.fullName : node.name;
17739
+ if ((nodeName === expectedName || expectedName === null) && node instanceof expectedType) {
17373
17740
  // Record the parse span with the element that is being closed. Any elements that are
17374
17741
  // removed from the element stack at this point are closed implicitly, so they won't get
17375
17742
  // an end source span (as there is no explicit closing element).
@@ -17379,8 +17746,7 @@ class _TreeBuilder {
17379
17746
  return !unexpectedCloseTagDetected;
17380
17747
  }
17381
17748
  // Blocks and most elements are not self closing.
17382
- if (node instanceof Block ||
17383
- (node instanceof Element && !this.getTagDefinition(node.name).closedByParent)) {
17749
+ if (node instanceof Block || !this._getTagDefinition(node)?.closedByParent) {
17384
17750
  // Note that we encountered an unexpected close tag but continue processing the element
17385
17751
  // stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
17386
17752
  // end tag in the stack.
@@ -17440,6 +17806,31 @@ class _TreeBuilder {
17440
17806
  new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
17441
17807
  return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
17442
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
+ }
17443
17834
  _consumeBlockOpen(token) {
17444
17835
  const parameters = [];
17445
17836
  while (this._peek.type === 27 /* TokenType.BLOCK_PARAMETER */) {
@@ -17530,10 +17921,11 @@ class _TreeBuilder {
17530
17921
  ? this._containerStack[this._containerStack.length - 1]
17531
17922
  : null;
17532
17923
  }
17533
- _getClosestParentElement() {
17924
+ _getClosestElementLikeParent() {
17534
17925
  for (let i = this._containerStack.length - 1; i > -1; i--) {
17535
- if (this._containerStack[i] instanceof Element) {
17536
- return this._containerStack[i];
17926
+ const current = this._containerStack[i];
17927
+ if (current instanceof Element || current instanceof Component) {
17928
+ return current;
17537
17929
  }
17538
17930
  }
17539
17931
  return null;
@@ -17547,18 +17939,57 @@ class _TreeBuilder {
17547
17939
  parent.children.push(node);
17548
17940
  }
17549
17941
  }
17550
- _getElementFullName(prefix, localName, parentElement) {
17551
- if (prefix === '') {
17552
- prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
17553
- if (prefix === '' && parentElement != null) {
17554
- const parentTagName = splitNsName(parentElement.name)[1];
17555
- const parentTagDefinition = this.getTagDefinition(parentTagName);
17556
- if (!parentTagDefinition.preventNamespaceInheritance) {
17557
- prefix = getNsPrefix(parentElement.name);
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);
17558
17989
  }
17559
17990
  }
17560
17991
  }
17561
- return mergeNsAndName(prefix, localName);
17992
+ return prefix;
17562
17993
  }
17563
17994
  }
17564
17995
  function lastOnStack(stack, element) {
@@ -17637,11 +18068,11 @@ class WhitespaceVisitor {
17637
18068
  if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
17638
18069
  // don't descent into elements where we need to preserve whitespaces
17639
18070
  // but still visit all attributes to eliminate one used as a market to preserve WS
17640
- 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);
17641
18072
  this.originalNodeMap?.set(newElement, element);
17642
18073
  return newElement;
17643
18074
  }
17644
- 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);
17645
18076
  this.originalNodeMap?.set(newElement, element);
17646
18077
  return newElement;
17647
18078
  }
@@ -17715,6 +18146,22 @@ class WhitespaceVisitor {
17715
18146
  visitLetDeclaration(decl, context) {
17716
18147
  return decl;
17717
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
+ }
17718
18165
  visit(_node, context) {
17719
18166
  // `visitAllWithSiblings` provides context necessary for ICU messages to be handled correctly.
17720
18167
  // Prefer that over calling `html.visitAll` directly on this visitor.
@@ -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
- const children = visitAll(this, el.children, context);
20619
- const attrs = {};
20620
- el.attrs.forEach((attr) => {
20621
- // Do not visit the attributes, translatable ones are top-level ASTs
20622
- attrs[attr.name] = attr.value;
20623
- });
20624
- const isVoid = getHtmlTagDefinition(el.name).isVoid;
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(element)) {
21502
+ if (hasI18nAttrs(node)) {
20977
21503
  this.hasI18nMeta = true;
20978
21504
  const attrs = [];
20979
21505
  const attrsMeta = {};
20980
- for (const attr of element.attrs) {
21506
+ for (const attr of node.attrs) {
20981
21507
  if (attr.name === I18N_ATTR) {
20982
21508
  // root 'i18n' node attribute
20983
- const i18n = element.i18n || attr.value;
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
- ? element.children
20998
- : visitAllWithSiblings(new WhitespaceVisitor(false /* preserveSignificantWhitespace */, originalNodeMap), element.children);
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
- element.i18n = message;
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
- if (isTrustedTypesSink(element.name, name)) {
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
- element.attrs = attrs;
21568
+ node.attrs = attrs;
21036
21569
  }
21037
21570
  }
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;
21056
- }
21057
- }
21058
- else {
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
@@ -27501,15 +27985,22 @@ function isAnimationLabel(name) {
27501
27985
  return name[0] == '@';
27502
27986
  }
27503
27987
  function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
27504
- const ctxs = [];
27505
- CssSelector.parse(selector).forEach((selector) => {
27506
- const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
27507
- const notElementNames = new Set(selector.notSelectors
27508
- .filter((selector) => selector.isElementSelector())
27509
- .map((selector) => selector.element));
27510
- const possibleElementNames = elementNames.filter((elementName) => !notElementNames.has(elementName));
27511
- ctxs.push(...possibleElementNames.map((elementName) => registry.securityContext(elementName, propName, isAttribute)));
27512
- });
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
+ }
27513
28004
  return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
27514
28005
  }
27515
28006
  /**
@@ -28594,6 +29085,17 @@ const BINDING_DELIMS = {
28594
29085
  EVENT: { start: '(', end: ')' },
28595
29086
  };
28596
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']);
28597
29099
  function htmlAstToRender3Ast(htmlNodes, bindingParser, options) {
28598
29100
  const transformer = new HtmlAstToIvyAst(bindingParser, options);
28599
29101
  const ivyNodes = visitAll(transformer, htmlNodes, htmlNodes);
@@ -28657,52 +29159,8 @@ class HtmlAstToIvyAst {
28657
29159
  }
28658
29160
  // Whether the element is a `<ng-template>`
28659
29161
  const isTemplateElement = isNgTemplate(element.name);
28660
- const parsedProperties = [];
28661
- const boundEvents = [];
28662
- const variables = [];
28663
- const references = [];
28664
- const attributes = [];
28665
- const i18nAttrsMeta = {};
28666
- const templateParsedProperties = [];
28667
- const templateVariables = [];
28668
- // Whether the element has any *-attribute
28669
- let elementHasInlineTemplate = false;
28670
- for (const attribute of element.attrs) {
28671
- let hasBinding = false;
28672
- const normalizedName = normalizeAttributeName(attribute.name);
28673
- // `*attr` defines template bindings
28674
- let isTemplateBinding = false;
28675
- if (attribute.i18n) {
28676
- i18nAttrsMeta[attribute.name] = attribute.i18n;
28677
- }
28678
- if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
28679
- // *-attributes
28680
- if (elementHasInlineTemplate) {
28681
- this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
28682
- }
28683
- isTemplateBinding = true;
28684
- elementHasInlineTemplate = true;
28685
- const templateValue = attribute.value;
28686
- const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
28687
- const parsedVariables = [];
28688
- const absoluteValueOffset = attribute.valueSpan
28689
- ? attribute.valueSpan.start.offset
28690
- : // If there is no value span the attribute does not have a value, like `attr` in
28691
- //`<div attr></div>`. In this case, point to one character beyond the last character of
28692
- // the attribute name.
28693
- attribute.sourceSpan.start.offset + attribute.name.length;
28694
- this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true /* isIvyAst */);
28695
- templateVariables.push(...parsedVariables.map((v) => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
28696
- }
28697
- else {
28698
- // Check for variables, events, property bindings, interpolation
28699
- hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
28700
- }
28701
- if (!hasBinding && !isTemplateBinding) {
28702
- // don't include the bindings as attributes as well in the AST
28703
- attributes.push(this.visitAttribute(attribute));
28704
- }
28705
- }
29162
+ const { attributes, boundEvents, references, variables, templateVariables, elementHasInlineTemplate, parsedProperties, templateParsedProperties, i18nAttrsMeta, } = this.prepareAttributes(element.attrs, isTemplateElement);
29163
+ const directives = this.extractDirectives(element);
28706
29164
  let children;
28707
29165
  if (preparsedElement.nonBindable) {
28708
29166
  // The `NonBindableVisitor` may need to return an array of nodes for blocks so we need
@@ -28717,44 +29175,24 @@ class HtmlAstToIvyAst {
28717
29175
  if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
28718
29176
  const selector = preparsedElement.selectAttr;
28719
29177
  const attrs = element.attrs.map((attr) => this.visitAttribute(attr));
28720
- 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);
28721
29179
  this.ngContentSelectors.push(selector);
28722
29180
  }
28723
29181
  else if (isTemplateElement) {
28724
29182
  // `<ng-template>`
28725
- const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
28726
- 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, [
28727
29185
  /* no template attributes */
28728
29186
  ], children, references, variables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
28729
29187
  }
28730
29188
  else {
28731
- const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
28732
- 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);
28733
29191
  }
28734
29192
  if (elementHasInlineTemplate) {
28735
29193
  // If this node is an inline-template (e.g. has *ngFor) then we need to create a template
28736
29194
  // node that contains this node.
28737
- // Moreover, if the node is an element, then we need to hoist its attributes to the template
28738
- // node for matching against content projection selectors.
28739
- const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta);
28740
- const templateAttrs = [];
28741
- attrs.literal.forEach((attr) => templateAttrs.push(attr));
28742
- attrs.bound.forEach((attr) => templateAttrs.push(attr));
28743
- const hoistedAttrs = parsedElement instanceof Element$1
28744
- ? {
28745
- attributes: parsedElement.attributes,
28746
- inputs: parsedElement.inputs,
28747
- outputs: parsedElement.outputs,
28748
- }
28749
- : { attributes: [], inputs: [], outputs: [] };
28750
- // For <ng-template>s with structural directives on them, avoid passing i18n information to
28751
- // the wrapping template to prevent unnecessary i18n instructions from being generated. The
28752
- // necessary i18n meta information will be extracted from child elements.
28753
- const i18n = isTemplateElement && isI18nRootElement ? undefined : element.i18n;
28754
- const name = parsedElement instanceof Template ? null : parsedElement.name;
28755
- parsedElement = new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, templateAttrs, [parsedElement], [
28756
- /* no references */
28757
- ], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, i18n);
29195
+ parsedElement = this.wrapInTemplate(parsedElement, templateParsedProperties, templateVariables, i18nAttrsMeta, isTemplateElement, isI18nRootElement);
28758
29196
  }
28759
29197
  if (isI18nRootElement) {
28760
29198
  this.inI18nBlock = false;
@@ -28818,6 +29256,43 @@ class HtmlAstToIvyAst {
28818
29256
  }
28819
29257
  return new LetDeclaration$1(decl.name, value, decl.sourceSpan, decl.nameSpan, decl.valueSpan);
28820
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
+ }
28821
29296
  visitBlockParameter() {
28822
29297
  return null;
28823
29298
  }
@@ -28894,8 +29369,8 @@ class HtmlAstToIvyAst {
28894
29369
  }
28895
29370
  return relatedBlocks;
28896
29371
  }
28897
- // convert view engine `ParsedProperty` to a format suitable for IVY
28898
- extractAttributes(elementName, properties, i18nPropsMeta) {
29372
+ /** Splits up the property attributes depending on whether they're static or bound. */
29373
+ categorizePropertyAttributes(elementName, properties, i18nPropsMeta) {
28899
29374
  const bound = [];
28900
29375
  const literal = [];
28901
29376
  properties.forEach((prop) => {
@@ -28915,6 +29390,65 @@ class HtmlAstToIvyAst {
28915
29390
  });
28916
29391
  return { bound, literal };
28917
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
+ }
28918
29452
  parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) {
28919
29453
  const name = normalizeAttributeName(attribute.name);
28920
29454
  const value = attribute.value;
@@ -29013,6 +29547,81 @@ class HtmlAstToIvyAst {
29013
29547
  const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null);
29014
29548
  return hasBinding;
29015
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
+ }
29016
29625
  _visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) {
29017
29626
  const valueNoNgsp = replaceNgsp(value);
29018
29627
  const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens);
@@ -29063,7 +29672,8 @@ class NonBindableVisitor {
29063
29672
  const children = visitAll(this, ast.children, null);
29064
29673
  return new Element$1(ast.name, visitAll(this, ast.attrs),
29065
29674
  /* inputs */ [],
29066
- /* outputs */ [], children,
29675
+ /* outputs */ [],
29676
+ /* directives */ [], children,
29067
29677
  /* references */ [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
29068
29678
  }
29069
29679
  visitComment(comment) {
@@ -29099,6 +29709,17 @@ class NonBindableVisitor {
29099
29709
  visitLetDeclaration(decl, context) {
29100
29710
  return new Text$3(`@let ${decl.name} = ${decl.value};`, decl.sourceSpan);
29101
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
+ }
29102
29723
  }
29103
29724
  const NON_BINDABLE_VISITOR = new NonBindableVisitor();
29104
29725
  function normalizeAttributeName(attrName) {
@@ -29955,6 +30576,7 @@ class Scope {
29955
30576
  }
29956
30577
  }
29957
30578
  visitElement(element) {
30579
+ element.directives.forEach((node) => node.visit(this));
29958
30580
  // `Element`s in the template may have `Reference`s which are captured in the scope.
29959
30581
  element.references.forEach((node) => this.visitReference(node));
29960
30582
  // Recurse into the `Element`'s children.
@@ -29962,6 +30584,7 @@ class Scope {
29962
30584
  this.elementsInScope.add(element);
29963
30585
  }
29964
30586
  visitTemplate(template) {
30587
+ template.directives.forEach((node) => node.visit(this));
29965
30588
  // References on a <ng-template> are defined in the outer scope, so capture them before
29966
30589
  // processing the template's child scope.
29967
30590
  template.references.forEach((node) => this.visitReference(node));
@@ -30016,6 +30639,12 @@ class Scope {
30016
30639
  visitLetDeclaration(decl) {
30017
30640
  this.maybeDeclare(decl);
30018
30641
  }
30642
+ visitComponent(component) {
30643
+ throw new Error('TODO');
30644
+ }
30645
+ visitDirective(directive) {
30646
+ throw new Error('TODO');
30647
+ }
30019
30648
  // Unused visitors.
30020
30649
  visitBoundAttribute(attr) { }
30021
30650
  visitBoundEvent(event) { }
@@ -30117,6 +30746,10 @@ class DirectiveBinder {
30117
30746
  // First, determine the HTML shape of the node for the purpose of directive matching.
30118
30747
  // Do this by building up a `CssSelector` for the node.
30119
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
+ }
30120
30753
  // Next, use the `SelectorMatcher` to get the list of directives on the node.
30121
30754
  const directives = [];
30122
30755
  this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
@@ -30216,6 +30849,12 @@ class DirectiveBinder {
30216
30849
  visitContent(content) {
30217
30850
  content.children.forEach((child) => child.visit(this));
30218
30851
  }
30852
+ visitComponent(component) {
30853
+ throw new Error('TODO');
30854
+ }
30855
+ visitDirective(directive) {
30856
+ throw new Error('TODO');
30857
+ }
30219
30858
  // Unused visitors.
30220
30859
  visitVariable(variable) { }
30221
30860
  visitReference(reference) { }
@@ -30346,6 +30985,7 @@ class TemplateBinder extends RecursiveAstVisitor {
30346
30985
  // Visit the inputs, outputs, and children of the element.
30347
30986
  element.inputs.forEach(this.visitNode);
30348
30987
  element.outputs.forEach(this.visitNode);
30988
+ element.directives.forEach(this.visitNode);
30349
30989
  element.children.forEach(this.visitNode);
30350
30990
  element.references.forEach(this.visitNode);
30351
30991
  }
@@ -30353,6 +30993,7 @@ class TemplateBinder extends RecursiveAstVisitor {
30353
30993
  // First, visit inputs, outputs and template attributes of the template node.
30354
30994
  template.inputs.forEach(this.visitNode);
30355
30995
  template.outputs.forEach(this.visitNode);
30996
+ template.directives.forEach(this.visitNode);
30356
30997
  template.templateAttrs.forEach(this.visitNode);
30357
30998
  template.references.forEach(this.visitNode);
30358
30999
  // Next, recurse into the template.
@@ -30370,6 +31011,12 @@ class TemplateBinder extends RecursiveAstVisitor {
30370
31011
  this.symbols.set(reference, this.rootNode);
30371
31012
  }
30372
31013
  }
31014
+ visitComponent(component) {
31015
+ throw new Error('TODO');
31016
+ }
31017
+ visitDirective(directive) {
31018
+ throw new Error('TODO');
31019
+ }
30373
31020
  // Unused template visitors
30374
31021
  visitText(text) { }
30375
31022
  visitTextAttribute(attribute) { }
@@ -31438,7 +32085,7 @@ class _Visitor {
31438
32085
  this._init(_VisitorMode.Merge, interpolationConfig);
31439
32086
  this._translations = translations;
31440
32087
  // Construct a single fake root element
31441
- const wrapper = new Element('wrapper', [], nodes, undefined, undefined, undefined);
32088
+ const wrapper = new Element('wrapper', [], [], nodes, undefined, undefined, undefined);
31442
32089
  const translatedNode = wrapper.visit(this, null);
31443
32090
  if (this._inI18nBlock) {
31444
32091
  this._reportError(nodes[nodes.length - 1], 'Unclosed block');
@@ -31524,7 +32171,41 @@ class _Visitor {
31524
32171
  return text;
31525
32172
  }
31526
32173
  visitElement(el, context) {
31527
- this._mayBeAddBlockChildren(el);
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);
31528
32209
  this._depth++;
31529
32210
  const wasInI18nNode = this._inI18nNode;
31530
32211
  const wasInImplicitNode = this._inImplicitNode;
@@ -31533,9 +32214,10 @@ class _Visitor {
31533
32214
  // Extract:
31534
32215
  // - top level nodes with the (implicit) "i18n" attribute if not already in a section
31535
32216
  // - ICU messages
31536
- const i18nAttr = _getI18nAttr(el);
32217
+ const nodeName = node instanceof Component ? node.tagName : node.name;
32218
+ const i18nAttr = _getI18nAttr(node);
31537
32219
  const i18nMeta = i18nAttr ? i18nAttr.value : '';
31538
- const isImplicit = this._implicitTags.some((tag) => el.name === tag) &&
32220
+ const isImplicit = this._implicitTags.some((tag) => nodeName === tag) &&
31539
32221
  !this._inIcu &&
31540
32222
  !this._isInTranslatableSection;
31541
32223
  const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
@@ -31543,29 +32225,29 @@ class _Visitor {
31543
32225
  if (!this._isInTranslatableSection && !this._inIcu) {
31544
32226
  if (i18nAttr || isTopLevelImplicit) {
31545
32227
  this._inI18nNode = true;
31546
- const message = this._addMessage(el.children, i18nMeta);
31547
- translatedChildNodes = this._translateMessage(el, message);
32228
+ const message = this._addMessage(node.children, i18nMeta);
32229
+ translatedChildNodes = this._translateMessage(node, message);
31548
32230
  }
31549
32231
  if (this._mode == _VisitorMode.Extract) {
31550
32232
  const isTranslatable = i18nAttr || isTopLevelImplicit;
31551
32233
  if (isTranslatable)
31552
- this._openTranslatableSection(el);
31553
- visitAll(this, el.children);
32234
+ this._openTranslatableSection(node);
32235
+ visitAll(this, node.children);
31554
32236
  if (isTranslatable)
31555
- this._closeTranslatableSection(el, el.children);
32237
+ this._closeTranslatableSection(node, node.children);
31556
32238
  }
31557
32239
  }
31558
32240
  else {
31559
32241
  if (i18nAttr || isTopLevelImplicit) {
31560
- this._reportError(el, 'Could not mark an element as translatable inside a translatable section');
32242
+ this._reportError(node, 'Could not mark an element as translatable inside a translatable section');
31561
32243
  }
31562
32244
  if (this._mode == _VisitorMode.Extract) {
31563
32245
  // Descend into child nodes for extraction
31564
- visitAll(this, el.children);
32246
+ visitAll(this, node.children);
31565
32247
  }
31566
32248
  }
31567
32249
  if (this._mode === _VisitorMode.Merge) {
31568
- const visitNodes = translatedChildNodes || el.children;
32250
+ const visitNodes = translatedChildNodes || node.children;
31569
32251
  visitNodes.forEach((child) => {
31570
32252
  const visited = child.visit(this, context);
31571
32253
  if (visited && !this._isInTranslatableSection) {
@@ -31575,48 +32257,29 @@ class _Visitor {
31575
32257
  }
31576
32258
  });
31577
32259
  }
31578
- this._visitAttributesOf(el);
32260
+ this._visitAttributesOf(node);
31579
32261
  this._depth--;
31580
32262
  this._inI18nNode = wasInI18nNode;
31581
32263
  this._inImplicitNode = wasInImplicitNode;
31582
32264
  if (this._mode === _VisitorMode.Merge) {
31583
- const translatedAttrs = this._translateAttributes(el);
31584
- return new Element(el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
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
+ }
31585
32271
  }
31586
32272
  return null;
31587
32273
  }
31588
- visitAttribute(attribute, context) {
31589
- throw new Error('unreachable code');
31590
- }
31591
- visitBlock(block, context) {
31592
- visitAll(this, block.children, context);
31593
- }
31594
- visitBlockParameter(parameter, context) { }
31595
- visitLetDeclaration(decl, context) { }
31596
- _init(mode, interpolationConfig) {
31597
- this._mode = mode;
31598
- this._inI18nBlock = false;
31599
- this._inI18nNode = false;
31600
- this._depth = 0;
31601
- this._inIcu = false;
31602
- this._msgCountAtSectionStart = undefined;
31603
- this._errors = [];
31604
- this._messages = [];
31605
- this._inImplicitNode = false;
31606
- this._createI18nMessage = createI18nMessageFactory(interpolationConfig, DEFAULT_CONTAINER_BLOCKS,
31607
- // When dropping significant whitespace we need to retain whitespace tokens or
31608
- // else we won't be able to reuse source spans because empty tokens would be
31609
- // removed and cause a mismatch.
31610
- /* retainEmptyTokens */ !this._preserveSignificantWhitespace,
31611
- /* preserveExpressionWhitespace */ this._preserveSignificantWhitespace);
31612
- }
31613
32274
  // looks for translatable attributes
31614
32275
  _visitAttributesOf(el) {
31615
32276
  const explicitAttrNameToValue = {};
31616
- const implicitAttrNames = this._implicitAttrs[el.name] || [];
32277
+ const implicitAttrNames = this._implicitAttrs[el instanceof Component ? el.tagName || '' : el.name] || [];
31617
32278
  el.attrs
31618
- .filter((attr) => attr.name.startsWith(_I18N_ATTR_PREFIX))
31619
- .forEach((attr) => (explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value));
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
+ });
31620
32283
  el.attrs.forEach((attr) => {
31621
32284
  if (attr.name in explicitAttrNameToValue) {
31622
32285
  this._addMessage([attr], explicitAttrNameToValue[attr.name]);
@@ -31689,16 +32352,15 @@ class _Visitor {
31689
32352
  return [];
31690
32353
  }
31691
32354
  // translate the attributes of an element and remove i18n specific attributes
31692
- _translateAttributes(el) {
31693
- const attributes = el.attrs;
32355
+ _translateAttributes(node) {
31694
32356
  const i18nParsedMessageMeta = {};
31695
- attributes.forEach((attr) => {
32357
+ const translatedAttributes = [];
32358
+ node.attrs.forEach((attr) => {
31696
32359
  if (attr.name.startsWith(_I18N_ATTR_PREFIX)) {
31697
32360
  i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value);
31698
32361
  }
31699
32362
  });
31700
- const translatedAttributes = [];
31701
- attributes.forEach((attr) => {
32363
+ node.attrs.forEach((attr) => {
31702
32364
  if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) {
31703
32365
  // strip i18n specific attributes
31704
32366
  return;
@@ -31716,11 +32378,11 @@ class _Visitor {
31716
32378
  translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined /* keySpan */, undefined /* valueSpan */, undefined /* valueTokens */, undefined /* i18n */));
31717
32379
  }
31718
32380
  else {
31719
- this._reportError(el, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
32381
+ this._reportError(node, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
31720
32382
  }
31721
32383
  }
31722
32384
  else {
31723
- this._reportError(el, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
32385
+ this._reportError(node, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
31724
32386
  }
31725
32387
  }
31726
32388
  else {
@@ -31729,6 +32391,9 @@ class _Visitor {
31729
32391
  });
31730
32392
  return translatedAttributes;
31731
32393
  }
32394
+ _translateDirectives(node) {
32395
+ return node.directives.map((dir) => new Directive(dir.name, this._translateAttributes(dir), dir.sourceSpan, dir.startSourceSpan, dir.endSourceSpan));
32396
+ }
31732
32397
  /**
31733
32398
  * Add the node as a child of the block when:
31734
32399
  * - we are in a block,
@@ -31804,7 +32469,7 @@ function _isClosingComment(n) {
31804
32469
  return !!(n instanceof Comment && n.value && n.value === '/i18n');
31805
32470
  }
31806
32471
  function _getI18nAttr(p) {
31807
- return p.attrs.find((attr) => attr.name === _I18N_ATTR) || null;
32472
+ return (p.attrs.find((attr) => attr instanceof Attribute && attr.name === _I18N_ATTR) || null);
31808
32473
  }
31809
32474
  function _parseMessageMeta(i18n) {
31810
32475
  if (!i18n)
@@ -31852,7 +32517,12 @@ class XmlParser extends Parser$1 {
31852
32517
  }
31853
32518
  parse(source, url, options = {}) {
31854
32519
  // Blocks and let declarations aren't supported in an XML context.
31855
- return super.parse(source, url, { ...options, tokenizeBlocks: false, tokenizeLet: false });
32520
+ return super.parse(source, url, {
32521
+ ...options,
32522
+ tokenizeBlocks: false,
32523
+ tokenizeLet: false,
32524
+ selectorlessEnabled: false,
32525
+ });
31856
32526
  }
31857
32527
  }
31858
32528
 
@@ -32076,6 +32746,8 @@ class XliffParser {
32076
32746
  visitBlock(block, context) { }
32077
32747
  visitBlockParameter(parameter, context) { }
32078
32748
  visitLetDeclaration(decl, context) { }
32749
+ visitComponent(component, context) { }
32750
+ visitDirective(directive, context) { }
32079
32751
  _addError(node, message) {
32080
32752
  this._errors.push(new I18nError(node.sourceSpan, message));
32081
32753
  }
@@ -32131,6 +32803,12 @@ let XmlToI18n$2 = class XmlToI18n {
32131
32803
  visitBlock(block, context) { }
32132
32804
  visitBlockParameter(parameter, context) { }
32133
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
+ }
32134
32812
  _addError(node, message) {
32135
32813
  this._errors.push(new I18nError(node.sourceSpan, message));
32136
32814
  }
@@ -32391,6 +33069,8 @@ class Xliff2Parser {
32391
33069
  visitBlock(block, context) { }
32392
33070
  visitBlockParameter(parameter, context) { }
32393
33071
  visitLetDeclaration(decl, context) { }
33072
+ visitComponent(component, context) { }
33073
+ visitDirective(directive, context) { }
32394
33074
  _addError(node, message) {
32395
33075
  this._errors.push(new I18nError(node.sourceSpan, message));
32396
33076
  }
@@ -32463,6 +33143,12 @@ let XmlToI18n$1 = class XmlToI18n {
32463
33143
  visitBlock(block, context) { }
32464
33144
  visitBlockParameter(parameter, context) { }
32465
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
+ }
32466
33152
  _addError(node, message) {
32467
33153
  this._errors.push(new I18nError(node.sourceSpan, message));
32468
33154
  }
@@ -32602,6 +33288,12 @@ class XtbParser {
32602
33288
  visitBlock(block, context) { }
32603
33289
  visitBlockParameter(block, context) { }
32604
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
+ }
32605
33297
  _addError(node, message) {
32606
33298
  this._errors.push(new I18nError(node.sourceSpan, message));
32607
33299
  }
@@ -32655,6 +33347,12 @@ class XmlToI18n {
32655
33347
  visitBlock(block, context) { }
32656
33348
  visitBlockParameter(block, context) { }
32657
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
+ }
32658
33356
  _addError(node, message) {
32659
33357
  this._errors.push(new I18nError(node.sourceSpan, message));
32660
33358
  }
@@ -33068,7 +33766,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
33068
33766
  function compileDeclareClassMetadata(metadata) {
33069
33767
  const definitionMap = new DefinitionMap();
33070
33768
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
33071
- definitionMap.set('version', literal('20.0.0-next.5'));
33769
+ definitionMap.set('version', literal('20.0.0-next.6'));
33072
33770
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33073
33771
  definitionMap.set('type', metadata.type);
33074
33772
  definitionMap.set('decorators', metadata.decorators);
@@ -33086,7 +33784,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
33086
33784
  callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
33087
33785
  callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
33088
33786
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
33089
- definitionMap.set('version', literal('20.0.0-next.5'));
33787
+ definitionMap.set('version', literal('20.0.0-next.6'));
33090
33788
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33091
33789
  definitionMap.set('type', metadata.type);
33092
33790
  definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -33181,7 +33879,7 @@ function createDirectiveDefinitionMap(meta) {
33181
33879
  const definitionMap = new DefinitionMap();
33182
33880
  const minVersion = getMinimumVersionForPartialOutput(meta);
33183
33881
  definitionMap.set('minVersion', literal(minVersion));
33184
- definitionMap.set('version', literal('20.0.0-next.5'));
33882
+ definitionMap.set('version', literal('20.0.0-next.6'));
33185
33883
  // e.g. `type: MyDirective`
33186
33884
  definitionMap.set('type', meta.type.value);
33187
33885
  if (meta.isStandalone !== undefined) {
@@ -33597,7 +34295,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
33597
34295
  function compileDeclareFactoryFunction(meta) {
33598
34296
  const definitionMap = new DefinitionMap();
33599
34297
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33600
- definitionMap.set('version', literal('20.0.0-next.5'));
34298
+ definitionMap.set('version', literal('20.0.0-next.6'));
33601
34299
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33602
34300
  definitionMap.set('type', meta.type.value);
33603
34301
  definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33632,7 +34330,7 @@ function compileDeclareInjectableFromMetadata(meta) {
33632
34330
  function createInjectableDefinitionMap(meta) {
33633
34331
  const definitionMap = new DefinitionMap();
33634
34332
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33635
- definitionMap.set('version', literal('20.0.0-next.5'));
34333
+ definitionMap.set('version', literal('20.0.0-next.6'));
33636
34334
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33637
34335
  definitionMap.set('type', meta.type.value);
33638
34336
  // Only generate providedIn property if it has a non-null value
@@ -33683,7 +34381,7 @@ function compileDeclareInjectorFromMetadata(meta) {
33683
34381
  function createInjectorDefinitionMap(meta) {
33684
34382
  const definitionMap = new DefinitionMap();
33685
34383
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33686
- definitionMap.set('version', literal('20.0.0-next.5'));
34384
+ definitionMap.set('version', literal('20.0.0-next.6'));
33687
34385
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33688
34386
  definitionMap.set('type', meta.type.value);
33689
34387
  definitionMap.set('providers', meta.providers);
@@ -33716,7 +34414,7 @@ function createNgModuleDefinitionMap(meta) {
33716
34414
  throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
33717
34415
  }
33718
34416
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33719
- definitionMap.set('version', literal('20.0.0-next.5'));
34417
+ definitionMap.set('version', literal('20.0.0-next.6'));
33720
34418
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33721
34419
  definitionMap.set('type', meta.type.value);
33722
34420
  // We only generate the keys in the metadata if the arrays contain values.
@@ -33767,7 +34465,7 @@ function compileDeclarePipeFromMetadata(meta) {
33767
34465
  function createPipeDefinitionMap(meta) {
33768
34466
  const definitionMap = new DefinitionMap();
33769
34467
  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33770
- definitionMap.set('version', literal('20.0.0-next.5'));
34468
+ definitionMap.set('version', literal('20.0.0-next.6'));
33771
34469
  definitionMap.set('ngImport', importExpr(Identifiers.core));
33772
34470
  // e.g. `type: MyPipe`
33773
34471
  definitionMap.set('type', meta.type.value);
@@ -33925,7 +34623,7 @@ function compileHmrUpdateCallback(definitions, constantStatements, meta) {
33925
34623
  * @description
33926
34624
  * Entry point for all public APIs of the compiler package.
33927
34625
  */
33928
- const VERSION = new Version('20.0.0-next.5');
34626
+ const VERSION = new Version('20.0.0-next.6');
33929
34627
 
33930
34628
  //////////////////////////////////////
33931
34629
  // THIS FILE HAS GLOBAL SIDE EFFECT //
@@ -33951,5 +34649,5 @@ const VERSION = new Version('20.0.0-next.5');
33951
34649
  // the late binding of the Compiler to the @angular/core for jit compilation.
33952
34650
  publishFacade(_global);
33953
34651
 
33954
- 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 };
33955
34653
  //# sourceMappingURL=compiler.mjs.map