@angular/platform-server 20.3.26 → 20.3.28

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.26
2
+ * @license Angular v20.3.28
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
@@ -755,6 +755,15 @@ function requireNodeUtils () {
755
755
  PLAINTEXT: true
756
756
  };
757
757
 
758
+ var hasRawContentFallback = {
759
+ // Text in these fallback raw-content elements is inert for browser parsing,
760
+ // but downstream SSR post-processing may reparse it without raw-text state.
761
+ IFRAME: true,
762
+ NOEMBED: true,
763
+ NOSCRIPT: true,
764
+ NOFRAMES: true
765
+ };
766
+
758
767
  var emptyElements = {
759
768
  area: true,
760
769
  base: true,
@@ -855,7 +864,7 @@ function requireNodeUtils () {
855
864
  * and unsafe behavior after de-serialization.
856
865
  */
857
866
  function escapeMatchingClosingTag(rawText, parentTag) {
858
- const parentClosingTag = '</' + parentTag;
867
+ const parentClosingTag = ('</' + parentTag).toLowerCase();
859
868
  if (!rawText.toLowerCase().includes(parentClosingTag)) {
860
869
  return rawText; // fast path
861
870
  }
@@ -865,11 +874,53 @@ function requireNodeUtils () {
865
874
  // would otherwise shift the replacement and leave a real `</tag>`
866
875
  // break-out in the output.
867
876
  return rawText.replace(
868
- new RegExp(parentClosingTag, 'ig'),
877
+ new RegExp(escapeRegExp(parentClosingTag), 'ig'),
869
878
  (m) => '&lt;' + m.slice(1)
870
879
  );
871
880
  }
872
881
 
882
+ function escapeRegExp(text) {
883
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
884
+ }
885
+
886
+ function escapeFallbackRawText(rawText, parentTag) {
887
+ var result = '';
888
+ var index = 0;
889
+
890
+ while (index < rawText.length) {
891
+ var commentStart = rawText.indexOf('<!--', index);
892
+ if (commentStart === -1) {
893
+ result += escape(rawText.slice(index));
894
+ break;
895
+ }
896
+
897
+ result += escape(rawText.slice(index, commentStart));
898
+
899
+ var commentEnd = findCommentEnd(rawText, commentStart + 4);
900
+ if (commentEnd === -1) {
901
+ result += escapeMatchingClosingTag(rawText.slice(commentStart), parentTag);
902
+ break;
903
+ }
904
+
905
+ // A complete HTML comment remains inert if downstream tooling reparses
906
+ // fallback raw text as normal HTML, so preserve its comment semantics.
907
+ result += escapeMatchingClosingTag(rawText.slice(commentStart, commentEnd), parentTag);
908
+ index = commentEnd;
909
+ }
910
+
911
+ return result;
912
+ }
913
+
914
+ function findCommentEnd(rawText, index) {
915
+ if (rawText.charAt(index) === '>')
916
+ return index + 1;
917
+ if (rawText.charAt(index) === '-' && rawText.charAt(index + 1) === '>')
918
+ return index + 2;
919
+
920
+ var match = CLOSING_COMMENT_REGEXP.exec(rawText.slice(index));
921
+ return match ? index + match.index + match[0].length : -1;
922
+ }
923
+
873
924
  const CLOSING_COMMENT_REGEXP = /--!?>/;
874
925
 
875
926
  /**
@@ -917,7 +968,7 @@ function requireNodeUtils () {
917
968
  // If an element can have raw content, this content may
918
969
  // potentially require escaping to avoid XSS.
919
970
  var upperTag = tagname.toUpperCase();
920
- if (hasRawContent[upperTag]) {
971
+ if (hasRawContent[upperTag] && !hasRawContentFallback[upperTag]) {
921
972
  ss = escapeMatchingClosingTag(ss, tagname);
922
973
  }
923
974
  if (html && extraNewLine[tagname] && ss.charAt(0)==='\n') s += '\n';
@@ -936,7 +987,9 @@ function requireNodeUtils () {
936
987
  parenttag = '';
937
988
 
938
989
  if (hasRawContent[parenttag]) {
939
- s += kid.data;
990
+ // Preserve actual child element markup in fallback elements such as
991
+ // <noscript>, but do not emit text-node payloads as raw HTML.
992
+ s += hasRawContentFallback[parenttag] ? escapeFallbackRawText(kid.data, parent.localName) : kid.data;
940
993
  } else {
941
994
  s += escape(kid.data);
942
995
  }