@angular/platform-server 20.3.29 → 20.3.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/fesm2022/init.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v20.3.29
2
+ * @license Angular v20.3.30
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -854,6 +854,23 @@ function requireNodeUtils () {
854
854
  return a.name;
855
855
  }
856
856
 
857
+ function fallbackRawContentTags(node) {
858
+ const tags = [];
859
+ while (node) {
860
+ if (node.nodeType === 1 /*ELEMENT_NODE*/) {
861
+ if (node.namespaceURI === NAMESPACE.HTML && hasRawContentFallback[node.tagName]) {
862
+ tags.push(node.localName);
863
+ }
864
+ node = node.parentNode;
865
+ } else if (node.nodeType === 11 /*DOCUMENT_FRAGMENT_NODE*/ && node._host) {
866
+ node = node._host;
867
+ } else {
868
+ node = node.parentNode;
869
+ }
870
+ }
871
+ return tags;
872
+ }
873
+
857
874
  /**
858
875
  * Escapes matching closing tag in a raw text.
859
876
  *
@@ -883,12 +900,22 @@ function requireNodeUtils () {
883
900
  return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
884
901
  }
885
902
 
886
- function escapeFallbackRawText(rawText, parentTag) {
887
- var result = '';
888
- var index = 0;
903
+ function escapeMatchingClosingTags(rawText, parentTag, ancestorTags) {
904
+ let result = escapeMatchingClosingTag(rawText, parentTag);
905
+ if (ancestorTags) {
906
+ for (const ancestorTag of ancestorTags) {
907
+ result = escapeMatchingClosingTag(result, ancestorTag);
908
+ }
909
+ }
910
+ return result;
911
+ }
912
+
913
+ function escapeFallbackRawText(rawText, parentTag, ancestorTags) {
914
+ let result = '';
915
+ let index = 0;
889
916
 
890
917
  while (index < rawText.length) {
891
- var commentStart = rawText.indexOf('<!--', index);
918
+ const commentStart = rawText.indexOf('<!--', index);
892
919
  if (commentStart === -1) {
893
920
  result += escape(rawText.slice(index));
894
921
  break;
@@ -896,15 +923,15 @@ function requireNodeUtils () {
896
923
 
897
924
  result += escape(rawText.slice(index, commentStart));
898
925
 
899
- var commentEnd = findCommentEnd(rawText, commentStart + 4);
926
+ const commentEnd = findCommentEnd(rawText, commentStart + 4);
900
927
  if (commentEnd === -1) {
901
- result += escapeMatchingClosingTag(rawText.slice(commentStart), parentTag);
928
+ result += escapeMatchingClosingTags(rawText.slice(commentStart), parentTag, ancestorTags);
902
929
  break;
903
930
  }
904
931
 
905
932
  // A complete HTML comment remains inert if downstream tooling reparses
906
933
  // fallback raw text as normal HTML, so preserve its comment semantics.
907
- result += escapeMatchingClosingTag(rawText.slice(commentStart, commentEnd), parentTag);
934
+ result += escapeMatchingClosingTags(rawText.slice(commentStart, commentEnd), parentTag, ancestorTags);
908
935
  index = commentEnd;
909
936
  }
910
937
 
@@ -917,7 +944,7 @@ function requireNodeUtils () {
917
944
  if (rawText.charAt(index) === '-' && rawText.charAt(index + 1) === '>')
918
945
  return index + 2;
919
946
 
920
- var match = CLOSING_COMMENT_REGEXP.exec(rawText.slice(index));
947
+ const match = CLOSING_COMMENT_REGEXP.exec(rawText.slice(index));
921
948
  return match ? index + match.index + match[0].length : -1;
922
949
  }
923
950
 
@@ -968,8 +995,12 @@ function requireNodeUtils () {
968
995
  // If an element can have raw content, this content may
969
996
  // potentially require escaping to avoid XSS.
970
997
  var upperTag = tagname.toUpperCase();
971
- if (hasRawContent[upperTag] && !hasRawContentFallback[upperTag]) {
998
+ if (hasRawContent[upperTag] && !hasRawContentFallback[upperTag] && ss.includes('</')) {
972
999
  ss = escapeMatchingClosingTag(ss, tagname);
1000
+ const fallbackTags = fallbackRawContentTags(parent);
1001
+ for (const fallbackTag of fallbackTags) {
1002
+ ss = escapeMatchingClosingTag(ss, fallbackTag);
1003
+ }
973
1004
  }
974
1005
  if (html && extraNewLine[tagname] && ss.charAt(0)==='\n') s += '\n';
975
1006
  // Serialize children and add end tag for all others
@@ -989,22 +1020,33 @@ function requireNodeUtils () {
989
1020
  if (hasRawContent[parenttag]) {
990
1021
  // Preserve actual child element markup in fallback elements such as
991
1022
  // <noscript>, but do not emit text-node payloads as raw HTML.
992
- s += hasRawContentFallback[parenttag] ? escapeFallbackRawText(kid.data, parent.localName) : kid.data;
1023
+ s += hasRawContentFallback[parenttag] ? escapeFallbackRawText(kid.data, parent.localName, fallbackRawContentTags(parent.parentNode)) : kid.data;
993
1024
  } else {
994
1025
  s += escape(kid.data);
995
1026
  }
996
1027
  break;
997
1028
  case 8: //COMMENT_NODE
998
- s += '<!--' + escapeClosingCommentTag(kid.data) + '-->';
1029
+ let commentData = escapeClosingCommentTag(kid.data);
1030
+ if (commentData.includes('</')) {
1031
+ const fallbackTags = fallbackRawContentTags(parent);
1032
+ for (const fallbackTag of fallbackTags) {
1033
+ commentData = escapeMatchingClosingTag(commentData, fallbackTag);
1034
+ }
1035
+ }
1036
+ s += '<!--' + commentData + '-->';
999
1037
  break;
1000
1038
  case 7: //PROCESSING_INSTRUCTION_NODE
1001
- const content = escapeProcessingInstructionContent(kid.data);
1039
+ let content = escapeProcessingInstructionContent(kid.data);
1040
+ if (content.includes('</')) {
1041
+ const fallbackTags = fallbackRawContentTags(parent);
1042
+ for (const fallbackTag of fallbackTags) {
1043
+ content = escapeMatchingClosingTag(content, fallbackTag);
1044
+ }
1045
+ }
1002
1046
  s += '<?' + kid.target + ' ' + content + '?>';
1003
1047
  break;
1004
1048
  case 10: //DOCUMENT_TYPE_NODE
1005
- s += '<!DOCTYPE ' + kid.name;
1006
-
1007
- s += '>';
1049
+ s += '<!DOCTYPE ' + kid.name + '>';
1008
1050
  break;
1009
1051
  default:
1010
1052
  utils.InvalidStateError();
@@ -7588,7 +7630,7 @@ function requireHtmlelts () {
7588
7630
  required: Boolean,
7589
7631
  readOnly: Boolean,
7590
7632
  checked: Boolean,
7591
- value: String,
7633
+ value: { type: String, treatNullAsEmptyString: true },
7592
7634
  src: URL,
7593
7635
  defaultChecked: {name: 'checked', type: Boolean},
7594
7636
  size: {type: 'unsigned long', default: 20, min: 1, setmin: 1},
@@ -8111,10 +8153,21 @@ function requireHtmlelts () {
8111
8153
  ctor: function HTMLTemplateElement(doc, localName, prefix) {
8112
8154
  HTMLElement.call(this, doc, localName, prefix);
8113
8155
  this._contentFragment = doc._templateDoc.createDocumentFragment();
8156
+ this._contentFragment._host = this;
8114
8157
  },
8115
8158
  props: {
8116
8159
  content: { get: function() { return this._contentFragment; } },
8117
- serialize: { value: function() { return this.content.serialize(); } }
8160
+ serialize: { value: function() { return this.content.serialize(); } },
8161
+ cloneNode: {
8162
+ value: function(deep) {
8163
+ var clone = HTMLElement.prototype.cloneNode.call(this, deep);
8164
+ if (deep) {
8165
+ clone._contentFragment = this._contentFragment.cloneNode(true);
8166
+ clone._contentFragment._host = clone;
8167
+ }
8168
+ return clone;
8169
+ }
8170
+ }
8118
8171
  }
8119
8172
  });
8120
8173