@angular/ssr 22.0.0-next.5 → 22.0.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/ssr",
3
- "version": "22.0.0-next.5",
3
+ "version": "22.0.0-next.6",
4
4
  "description": "Angular server side rendering utilities",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,14 +29,14 @@
29
29
  },
30
30
  "devDependencies": {
31
31
  "@angular-devkit/schematics": "workspace:*",
32
- "@angular/common": "22.0.0-next.6",
33
- "@angular/compiler": "22.0.0-next.6",
34
- "@angular/core": "22.0.0-next.6",
35
- "@angular/platform-browser": "22.0.0-next.6",
36
- "@angular/platform-server": "22.0.0-next.6",
37
- "@angular/router": "22.0.0-next.6",
32
+ "@angular/common": "22.0.0-next.8",
33
+ "@angular/compiler": "22.0.0-next.8",
34
+ "@angular/core": "22.0.0-next.8",
35
+ "@angular/platform-browser": "22.0.0-next.8",
36
+ "@angular/platform-server": "22.0.0-next.8",
37
+ "@angular/router": "22.0.0-next.8",
38
38
  "@schematics/angular": "workspace:*",
39
- "beasties": "0.4.1"
39
+ "beasties": "0.4.2"
40
40
  },
41
41
  "sideEffects": false,
42
42
  "schematics": "./schematics/collection.json",
@@ -449,7 +449,7 @@ License: MIT
449
449
 
450
450
  The MIT License (MIT)
451
451
 
452
- Copyright 2013 Andrey Sitnik <andrey@sitnik.ru>
452
+ Copyright 2013 Andrey Sitnik <andrey@sitnik.es>
453
453
 
454
454
  Permission is hereby granted, free of charge, to any person obtaining a copy of
455
455
  this software and associated documentation files (the "Software"), to deal in
@@ -599,6 +599,18 @@ function requireStringifier () {
599
599
  if (hasRequiredStringifier) return stringifier;
600
600
  hasRequiredStringifier = 1;
601
601
 
602
+ // Escapes sequences that could break out of an HTML <style> context.
603
+ // Uses CSS unicode escaping (\3c = '<') which is valid CSS and parsed
604
+ // correctly by all compliant CSS consumers.
605
+ const STYLE_TAG = /(<)(\/?style\b)/gi;
606
+ const COMMENT_OPEN = /(<)(!--)/g;
607
+
608
+ function escapeHTMLInCSS(str) {
609
+ if (typeof str !== 'string') return str
610
+ if (!str.includes('<')) return str
611
+ return str.replace(STYLE_TAG, '\\3c $2').replace(COMMENT_OPEN, '\\3c $2')
612
+ }
613
+
602
614
  const DEFAULT_RAW = {
603
615
  after: '\n',
604
616
  beforeClose: '\n',
@@ -637,7 +649,7 @@ function requireStringifier () {
637
649
  this.block(node, name + params);
638
650
  } else {
639
651
  let end = (node.raws.between || '') + (semicolon ? ';' : '');
640
- this.builder(name + params + end, node);
652
+ this.builder(escapeHTMLInCSS(name + params + end), node);
641
653
  }
642
654
  }
643
655
 
@@ -672,7 +684,7 @@ function requireStringifier () {
672
684
 
673
685
  block(node, start) {
674
686
  let between = this.raw(node, 'between', 'beforeOpen');
675
- this.builder(start + between + '{', node, 'start');
687
+ this.builder(escapeHTMLInCSS(start + between) + '{', node, 'start');
676
688
 
677
689
  let after;
678
690
  if (node.nodes && node.nodes.length) {
@@ -682,7 +694,7 @@ function requireStringifier () {
682
694
  after = this.raw(node, 'after', 'emptyBody');
683
695
  }
684
696
 
685
- if (after) this.builder(after);
697
+ if (after) this.builder(escapeHTMLInCSS(after));
686
698
  this.builder('}', node, 'end');
687
699
  }
688
700
 
@@ -694,10 +706,11 @@ function requireStringifier () {
694
706
  }
695
707
 
696
708
  let semicolon = this.raw(node, 'semicolon');
709
+ let isDocument = node.type === 'document';
697
710
  for (let i = 0; i < node.nodes.length; i++) {
698
711
  let child = node.nodes[i];
699
712
  let before = this.raw(child, 'before');
700
- if (before) this.builder(before);
713
+ if (before) this.builder(isDocument ? before : escapeHTMLInCSS(before));
701
714
  this.stringify(child, last !== i || semicolon);
702
715
  }
703
716
  }
@@ -705,7 +718,7 @@ function requireStringifier () {
705
718
  comment(node) {
706
719
  let left = this.raw(node, 'left', 'commentLeft');
707
720
  let right = this.raw(node, 'right', 'commentRight');
708
- this.builder('/*' + left + node.text + right + '*/', node);
721
+ this.builder(escapeHTMLInCSS('/*' + left + node.text + right + '*/'), node);
709
722
  }
710
723
 
711
724
  decl(node, semicolon) {
@@ -717,7 +730,7 @@ function requireStringifier () {
717
730
  }
718
731
 
719
732
  if (semicolon) string += ';';
720
- this.builder(string, node);
733
+ this.builder(escapeHTMLInCSS(string), node);
721
734
  }
722
735
 
723
736
  document(node) {
@@ -923,13 +936,17 @@ function requireStringifier () {
923
936
 
924
937
  root(node) {
925
938
  this.body(node);
926
- if (node.raws.after) this.builder(node.raws.after);
939
+ if (node.raws.after) {
940
+ let after = node.raws.after;
941
+ let isDocument = node.parent && node.parent.type === 'document';
942
+ this.builder(isDocument ? after : escapeHTMLInCSS(after));
943
+ }
927
944
  }
928
945
 
929
946
  rule(node) {
930
947
  this.block(node, this.rawValue(node, 'selector'));
931
948
  if (node.raws.ownSemicolon) {
932
- this.builder(node.raws.ownSemicolon, node, 'end');
949
+ this.builder(escapeHTMLInCSS(node.raws.ownSemicolon), node, 'end');
933
950
  }
934
951
  }
935
952
 
@@ -2126,7 +2143,8 @@ function requirePreviousMap () {
2126
2143
  return fromBase64(text.substr(baseUriMatch[0].length))
2127
2144
  }
2128
2145
 
2129
- let encoding = text.match(/data:application\/json;([^,]+),/)[1];
2146
+ let encoding = text.slice('data:application/json;'.length);
2147
+ encoding = encoding.slice(0, encoding.indexOf(','));
2130
2148
  throw new Error('Unsupported source map encoding ' + encoding)
2131
2149
  }
2132
2150
 
@@ -2369,7 +2387,15 @@ function requireInput () {
2369
2387
  );
2370
2388
  }
2371
2389
 
2372
- result.input = { column, endColumn, endLine, endOffset, line, offset, source: this.css };
2390
+ result.input = {
2391
+ column,
2392
+ endColumn,
2393
+ endLine,
2394
+ endOffset,
2395
+ line,
2396
+ offset,
2397
+ source: this.css
2398
+ };
2373
2399
  if (this.file) {
2374
2400
  if (pathToFileURL) {
2375
2401
  result.input.url = pathToFileURL(this.file).toString();
@@ -4736,7 +4762,7 @@ function requireNoWorkResult () {
4736
4762
 
4737
4763
  let MapGenerator = requireMapGenerator();
4738
4764
  let parse = requireParse();
4739
- const Result = requireResult();
4765
+ let Result = requireResult();
4740
4766
  let stringify = requireStringify();
4741
4767
  let warnOnce = requireWarnOnce();
4742
4768
 
@@ -4886,7 +4912,7 @@ function requireProcessor () {
4886
4912
 
4887
4913
  class Processor {
4888
4914
  constructor(plugins = []) {
4889
- this.version = '8.5.8';
4915
+ this.version = '8.5.10';
4890
4916
  this.plugins = this.normalize(plugins);
4891
4917
  }
4892
4918
 
@@ -11647,23 +11673,21 @@ function validateMediaQuery(query) {
11647
11673
  return true;
11648
11674
  }
11649
11675
 
11650
- let classCache = null;
11651
- let idCache = null;
11652
11676
  function buildCache(container) {
11653
- classCache = /* @__PURE__ */ new Set();
11654
- idCache = /* @__PURE__ */ new Set();
11677
+ container._classCache = /* @__PURE__ */ new Set();
11678
+ container._idCache = /* @__PURE__ */ new Set();
11655
11679
  const queue = [container];
11656
11680
  while (queue.length) {
11657
11681
  const node = queue.shift();
11658
11682
  if (node.hasAttribute?.("class")) {
11659
11683
  const classList = node.getAttribute("class").trim().split(" ");
11660
11684
  classList.forEach((cls) => {
11661
- classCache.add(cls);
11685
+ container._classCache.add(cls);
11662
11686
  });
11663
11687
  }
11664
11688
  if (node.hasAttribute?.("id")) {
11665
11689
  const id = node.getAttribute("id").trim();
11666
- idCache.add(id);
11690
+ container._idCache.add(id);
11667
11691
  }
11668
11692
  if ("children" in node) {
11669
11693
  queue.push(...node.children.filter((child) => child.type === "tag"));
@@ -11749,10 +11773,8 @@ function extendElement(element) {
11749
11773
  },
11750
11774
  setAttribute: {
11751
11775
  value(name, value) {
11752
- if (this.attribs == null)
11753
- this.attribs = {};
11754
- if (value == null)
11755
- value = "";
11776
+ this.attribs ??= {};
11777
+ value ??= "";
11756
11778
  this.attribs[name] = value;
11757
11779
  }
11758
11780
  },
@@ -11870,15 +11892,16 @@ function cachedQuerySelector(sel, node) {
11870
11892
  selectorTokens = parseRelevantSelectors(sel);
11871
11893
  selectorTokensCache.set(sel, selectorTokens);
11872
11894
  }
11873
- if (selectorTokens) {
11895
+ if (selectorTokens && node._classCache && node._idCache) {
11874
11896
  for (const token of selectorTokens) {
11875
- if (token.name === "class") {
11876
- return classCache.has(token.value);
11897
+ if (token.name === "class" && !node._classCache.has(token.value)) {
11898
+ return false;
11877
11899
  }
11878
- if (token.name === "id") {
11879
- return idCache.has(token.value);
11900
+ if (token.name === "id" && !node._idCache.has(token.value)) {
11901
+ return false;
11880
11902
  }
11881
11903
  }
11904
+ return true;
11882
11905
  }
11883
11906
  return !!selectOne(sel, node);
11884
11907
  }
@@ -11888,7 +11911,7 @@ function parseRelevantSelectors(sel) {
11888
11911
  for (let i = 0; i < tokens.length; i++) {
11889
11912
  const tokenGroup = tokens[i];
11890
11913
  if (tokenGroup?.length !== 1) {
11891
- continue;
11914
+ return null;
11892
11915
  }
11893
11916
  const token = tokenGroup[0];
11894
11917
  if (token?.type === "attribute" && (token.name === "class" || token.name === "id")) {
@@ -11937,6 +11960,15 @@ const removePseudoClassesAndElementsPattern = /(?<!\\)::?[a-z-]+(?:\(.+\))?/gi;
11937
11960
  const implicitUniversalPattern = /([>+~])\s*(?!\1)([>+~])/g;
11938
11961
  const emptyCombinatorPattern = /([>+~])\s*(?=\1|$)/g;
11939
11962
  const removeTrailingCommasPattern = /\(\s*,|,\s*\)/g;
11963
+ const LEADING_SLASH_OR_QUERY_RE = /^\/(?!\/)|[?#].*$/g;
11964
+ const PUBLIC_PATH_RE = /(^\/(?!\/)|\/$)/g;
11965
+ const REMOTE_URL_RE = /^https?:\/\//;
11966
+ const BEFORE_AFTER_PSEUDO_RE = /^::?(?:before|after)$/;
11967
+ const FONT_FAMILY_RE = /\bfont(?:-family)?\b/i;
11968
+ const BEASTIES_COMMENT_RE = /^(?<!! )beasties:(.*)/;
11969
+ const LEADING_SLASH_RE = /^\//;
11970
+ const WHITESPACE_RE = /\s+/;
11971
+ const URL_RE = /url\s*\(\s*(['"]?)(.+?)\1\s*\)/;
11940
11972
  class Beasties {
11941
11973
  #selectorCache = /* @__PURE__ */ new Map();
11942
11974
  options;
@@ -12062,12 +12094,12 @@ class Beasties {
12062
12094
  async getCssAsset(href, _style) {
12063
12095
  const outputPath = this.options.path;
12064
12096
  const publicPath = this.options.publicPath;
12065
- let normalizedPath = href.replace(/^\/(?!\/)|[?#].*$/g, "");
12066
- const pathPrefix = `${(publicPath || "").replace(/(^\/(?!\/)|\/$)/g, "")}/`;
12097
+ let normalizedPath = href.replace(LEADING_SLASH_OR_QUERY_RE, "");
12098
+ const pathPrefix = `${(publicPath || "").replace(PUBLIC_PATH_RE, "")}/`;
12067
12099
  if (normalizedPath.startsWith(pathPrefix) && !(pathPrefix === "/" && normalizedPath.startsWith("//"))) {
12068
- normalizedPath = normalizedPath.substring(pathPrefix.length).replace(/^\//, "");
12100
+ normalizedPath = normalizedPath.substring(pathPrefix.length).replace(LEADING_SLASH_RE, "");
12069
12101
  }
12070
- const isRemote = /^https?:\/\//.test(normalizedPath) || normalizedPath.startsWith("//");
12102
+ const isRemote = REMOTE_URL_RE.test(normalizedPath) || normalizedPath.startsWith("//");
12071
12103
  if (isRemote) {
12072
12104
  if (this.options.remote === true) {
12073
12105
  try {
@@ -12271,7 +12303,7 @@ class Beasties {
12271
12303
  processStyle(style, document) {
12272
12304
  if (style.$$reduce === false)
12273
12305
  return;
12274
- const name = style.$$name ? style.$$name.replace(/^\//, "") : "inline CSS";
12306
+ const name = style.$$name ? style.$$name.replace(LEADING_SLASH_RE, "") : "inline CSS";
12275
12307
  const options = this.options;
12276
12308
  const beastiesContainer = document.beastiesContainer;
12277
12309
  let keyframesMode = options.keyframes ?? "critical";
@@ -12298,7 +12330,7 @@ class Beasties {
12298
12330
  ast,
12299
12331
  markOnly((rule) => {
12300
12332
  if (rule.type === "comment") {
12301
- const beastiesComment = rule.text.match(/^(?<!! )beasties:(.*)/);
12333
+ const beastiesComment = rule.text.match(BEASTIES_COMMENT_RE);
12302
12334
  const command = beastiesComment && beastiesComment[1];
12303
12335
  if (command) {
12304
12336
  switch (command) {
@@ -12347,7 +12379,7 @@ class Beasties {
12347
12379
  });
12348
12380
  if (isAllowedRule)
12349
12381
  return true;
12350
- if (sel === ":root" || sel === "html" || sel === "body" || sel[0] === ":" && /^::?(?:before|after)$/.test(sel)) {
12382
+ if (sel === ":root" || sel === "html" || sel === "body" || sel[0] === ":" && BEFORE_AFTER_PSEUDO_RE.test(sel)) {
12351
12383
  return true;
12352
12384
  }
12353
12385
  sel = this.normalizeCssSelector(sel);
@@ -12368,11 +12400,11 @@ class Beasties {
12368
12400
  if (!("prop" in decl)) {
12369
12401
  continue;
12370
12402
  }
12371
- if (shouldInlineFonts && /\bfont(?:-family)?\b/i.test(decl.prop)) {
12403
+ if (shouldInlineFonts && FONT_FAMILY_RE.test(decl.prop)) {
12372
12404
  criticalFonts += ` ${decl.value}`;
12373
12405
  }
12374
12406
  if (decl.prop === "animation" || decl.prop === "animation-name") {
12375
- for (const name2 of decl.value.split(/\s+/)) {
12407
+ for (const name2 of decl.value.split(WHITESPACE_RE)) {
12376
12408
  const nameTrimmed = name2.trim();
12377
12409
  if (nameTrimmed)
12378
12410
  criticalKeyframeNames.add(nameTrimmed);
@@ -12415,7 +12447,7 @@ class Beasties {
12415
12447
  continue;
12416
12448
  }
12417
12449
  if (decl.prop === "src") {
12418
- src = (decl.value.match(/url\s*\(\s*(['"]?)(.+?)\1\s*\)/) || [])[2];
12450
+ src = (decl.value.match(URL_RE) || [])[2];
12419
12451
  } else if (decl.prop === "font-family") {
12420
12452
  family = decl.value;
12421
12453
  }