Skip to content

Commit 1534f46

Browse files
committed
refactor: replace critters with beasties
The Critters project has been transferred to the Nuxt team, who will now manage its development and has been renamed to Beasties. See: https://github.com/danielroe/beasties (cherry picked from commit 15677d0)
1 parent e42d841 commit 1534f46

File tree

19 files changed

+314
-153
lines changed

19 files changed

+314
-153
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@
124124
"ansi-colors": "4.1.3",
125125
"autoprefixer": "10.4.20",
126126
"babel-loader": "9.2.1",
127+
"beasties": "0.1.0",
127128
"browser-sync": "3.0.3",
128129
"browserslist": "^4.21.5",
129130
"buffer": "6.0.3",
130131
"chokidar": "4.0.1",
131132
"copy-webpack-plugin": "12.0.2",
132-
"critters": "0.0.25",
133133
"css-loader": "7.1.2",
134134
"debug": "^4.1.1",
135135
"esbuild": "0.24.0",

packages/angular/build/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ ts_library(
7878
"@npm//@types/semver",
7979
"@npm//@types/watchpack",
8080
"@npm//@vitejs/plugin-basic-ssl",
81+
"@npm//beasties",
8182
"@npm//browserslist",
82-
"@npm//critters",
8383
"@npm//esbuild",
8484
"@npm//esbuild-wasm",
8585
"@npm//fast-glob",

packages/angular/build/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"@babel/plugin-syntax-import-attributes": "7.25.9",
2727
"@inquirer/confirm": "5.0.0",
2828
"@vitejs/plugin-basic-ssl": "1.1.0",
29+
"beasties": "0.1.0",
2930
"browserslist": "^4.23.0",
30-
"critters": "0.0.25",
3131
"esbuild": "0.24.0",
3232
"fast-glob": "3.3.2",
3333
"https-proxy-agent": "7.0.5",

packages/angular/build/src/tools/esbuild/commonjs-checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ export function checkCommonJSModules(
5050
allowedRequests.add('xhr2');
5151

5252
// Packages used by @angular/ssr.
53-
// While critters is ESM it has a number of direct and transtive CJS deps.
53+
// While beasties is ESM it has a number of direct and transtive CJS deps.
5454
allowedRequests.add('express');
55-
allowedRequests.add('critters');
55+
allowedRequests.add('beasties');
5656

5757
// Find all entry points that contain code (JS/TS)
5858
const files: string[] = [];

packages/angular/build/src/tools/esbuild/global-styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export function createGlobalStylesBundleOptions(
7474
);
7575

7676
// Keep special CSS comments `/*! comment */` in place when `removeSpecialComments` is disabled.
77-
// These comments are special for a number of CSS tools such as Critters and PurgeCSS.
77+
// These comments are special for a number of CSS tools such as Beasties and PurgeCSS.
7878
buildOptions.legalComments = optimizationOptions.styles?.removeSpecialComments
7979
? 'none'
8080
: 'inline';

packages/angular/build/src/typings.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
// The `bundled_critters` causes issues with module mappings in Bazel,
9+
// The `bundled_beasties` causes issues with module mappings in Bazel,
1010
// leading to unexpected behavior with esbuild. Specifically, the problem occurs
1111
// when esbuild resolves to a different module or version than expected, due to
1212
// how Bazel handles module mappings.

packages/angular/build/src/utils/index-file/inline-critical-css.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import Critters from 'critters';
9+
import Beasties from 'beasties';
1010
import { readFile } from 'node:fs/promises';
1111

1212
/**
13-
* Pattern used to extract the media query set by Critters in an `onload` handler.
13+
* Pattern used to extract the media query set by Beasties in an `onload` handler.
1414
*/
1515
const MEDIA_SET_HANDLER_PATTERN = /^this\.media=["'](.*)["'];?$/;
1616

1717
/**
18-
* Name of the attribute used to save the Critters media query so it can be re-assigned on load.
18+
* Name of the attribute used to save the Beasties media query so it can be re-assigned on load.
1919
*/
2020
const CSP_MEDIA_ATTR = 'ngCspMedia';
2121

@@ -58,8 +58,7 @@ const LINK_LOAD_SCRIPT_CONTENT = `
5858
};
5959
6060
documentElement.addEventListener('load', listener, true);
61-
})();
62-
`.trim();
61+
})();`;
6362

6463
export interface InlineCriticalCssProcessOptions {
6564
outputPath: string;
@@ -98,14 +97,14 @@ interface PartialDocument {
9897
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
9998

10099
// We use Typescript declaration merging because `embedLinkedStylesheet` it's not declared in
101-
// the `Critters` types which means that we can't call the `super` implementation.
102-
interface CrittersBase {
100+
// the `Beasties` types which means that we can't call the `super` implementation.
101+
interface BeastiesBase {
103102
embedLinkedStylesheet(link: PartialHTMLElement, document: PartialDocument): Promise<unknown>;
104103
}
105-
class CrittersBase extends Critters {}
104+
class BeastiesBase extends Beasties {}
106105
/* eslint-enable @typescript-eslint/no-unsafe-declaration-merging */
107106

108-
class CrittersExtended extends CrittersBase {
107+
class BeastiesExtended extends BeastiesBase {
109108
readonly warnings: string[] = [];
110109
readonly errors: string[] = [];
111110
private addedCspScriptsDocuments = new WeakSet<PartialDocument>();
@@ -143,7 +142,7 @@ class CrittersExtended extends CrittersBase {
143142
}
144143

145144
/**
146-
* Override of the Critters `embedLinkedStylesheet` method
145+
* Override of the Beasties `embedLinkedStylesheet` method
147146
* that makes it work with Angular's CSP APIs.
148147
*/
149148
override async embedLinkedStylesheet(
@@ -165,19 +164,19 @@ class CrittersExtended extends CrittersBase {
165164
const cspNonce = this.findCspNonce(document);
166165

167166
if (cspNonce) {
168-
const crittersMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
167+
const beastiesMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
169168

170-
if (crittersMedia) {
171-
// If there's a Critters-generated `onload` handler and the file has an Angular CSP nonce,
169+
if (beastiesMedia) {
170+
// If there's a Beasties-generated `onload` handler and the file has an Angular CSP nonce,
172171
// we have to remove the handler, because it's incompatible with CSP. We save the value
173172
// in a different attribute and we generate a script tag with the nonce that uses
174173
// `addEventListener` to apply the media query instead.
175174
link.removeAttribute('onload');
176-
link.setAttribute(CSP_MEDIA_ATTR, crittersMedia[1]);
175+
link.setAttribute(CSP_MEDIA_ATTR, beastiesMedia[1]);
177176
this.conditionallyInsertCspLoadingScript(document, cspNonce, link);
178177
}
179178

180-
// Ideally we would hook in at the time Critters inserts the `style` tags, but there isn't
179+
// Ideally we would hook in at the time Beasties inserts the `style` tags, but there isn't
181180
// a way of doing that at the moment so we fall back to doing it any time a `link` tag is
182181
// inserted. We mitigate it by only iterating the direct children of the `<head>` which
183182
// should be pretty shallow.
@@ -200,7 +199,7 @@ class CrittersExtended extends CrittersBase {
200199
return this.documentNonces.get(document)!;
201200
}
202201

203-
// HTML attribute are case-insensitive, but the parser used by Critters is case-sensitive.
202+
// HTML attribute are case-insensitive, but the parser used by Beasties is case-sensitive.
204203
const nonceElement = document.querySelector('[ngCspNonce], [ngcspnonce]');
205204
const cspNonce =
206205
nonceElement?.getAttribute('ngCspNonce') || nonceElement?.getAttribute('ngcspnonce') || null;
@@ -240,16 +239,16 @@ export class InlineCriticalCssProcessor {
240239
html: string,
241240
options: InlineCriticalCssProcessOptions,
242241
): Promise<{ content: string; warnings: string[]; errors: string[] }> {
243-
const critters = new CrittersExtended({ ...this.options, ...options });
244-
const content = await critters.process(html);
242+
const beasties = new BeastiesExtended({ ...this.options, ...options });
243+
const content = await beasties.process(html);
245244

246245
return {
247246
// Clean up value from value less attributes.
248247
// This is caused because parse5 always requires attributes to have a string value.
249248
// nomodule="" defer="" -> nomodule defer.
250249
content: content.replace(/(\s(?:defer|nomodule))=""/g, '$1'),
251-
errors: critters.errors,
252-
warnings: critters.warnings,
250+
errors: beasties.errors,
251+
warnings: beasties.warnings,
253252
};
254253
}
255254
}

packages/angular/ssr/BUILD.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ts_library(
1919
module_name = "@angular/ssr",
2020
tsconfig = "//:tsconfig-build-ng",
2121
deps = [
22-
"//packages/angular/ssr/third_party/critters:bundled_critters_lib",
22+
"//packages/angular/ssr/third_party/beasties:bundled_beasties_lib",
2323
"//packages/angular/ssr/tokens",
2424
"@npm//@angular/common",
2525
"@npm//@angular/core",
@@ -34,13 +34,13 @@ ng_package(
3434
package_name = "@angular/ssr",
3535
srcs = [
3636
":package.json",
37-
"//packages/angular/ssr/third_party/critters:bundled_critters_lib",
37+
"//packages/angular/ssr/third_party/beasties:bundled_beasties_lib",
3838
],
3939
externals = [
4040
"@angular/ssr",
4141
"@angular/ssr/node",
4242
"@angular/ssr/tokens",
43-
"../../third_party/critters",
43+
"../../third_party/beasties",
4444
],
4545
nested_packages = [
4646
"//packages/angular/ssr/schematics:npm_package",

packages/angular/ssr/node/src/common-engine/inline-css-processor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class CommonEngineInlineCriticalCssProcessor {
1313
private readonly resourceCache = new Map<string, string>();
1414

1515
async process(html: string, outputPath: string | undefined): Promise<string> {
16-
const critters = new InlineCriticalCssProcessor(async (path) => {
16+
const beasties = new InlineCriticalCssProcessor(async (path) => {
1717
let resourceContent = this.resourceCache.get(path);
1818
if (resourceContent === undefined) {
1919
resourceContent = await readFile(path, 'utf-8');
@@ -23,6 +23,6 @@ export class CommonEngineInlineCriticalCssProcessor {
2323
return resourceContent;
2424
}, outputPath);
2525

26-
return critters.process(html);
26+
return beasties.process(html);
2727
}
2828
}

packages/angular/ssr/src/utils/inline-critical-css.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import Critters from '../../third_party/critters';
9+
import Beasties from '../../third_party/beasties';
1010

1111
/**
12-
* Pattern used to extract the media query set by Critters in an `onload` handler.
12+
* Pattern used to extract the media query set by Beasties in an `onload` handler.
1313
*/
1414
const MEDIA_SET_HANDLER_PATTERN = /^this\.media=["'](.*)["'];?$/;
1515

1616
/**
17-
* Name of the attribute used to save the Critters media query so it can be re-assigned on load.
17+
* Name of the attribute used to save the Beasties media query so it can be re-assigned on load.
1818
*/
1919
const CSP_MEDIA_ATTR = 'ngCspMedia';
2020

@@ -57,8 +57,7 @@ const LINK_LOAD_SCRIPT_CONTENT = `
5757
};
5858
5959
documentElement.addEventListener('load', listener, true);
60-
})();
61-
`.trim();
60+
})();`;
6261

6362
/** Partial representation of an `HTMLElement`. */
6463
interface PartialHTMLElement {
@@ -87,14 +86,14 @@ interface PartialDocument {
8786
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
8887

8988
// We use Typescript declaration merging because `embedLinkedStylesheet` it's not declared in
90-
// the `Critters` types which means that we can't call the `super` implementation.
91-
interface CrittersBase {
89+
// the `Beasties` types which means that we can't call the `super` implementation.
90+
interface BeastiesBase {
9291
embedLinkedStylesheet(link: PartialHTMLElement, document: PartialDocument): Promise<unknown>;
9392
}
94-
class CrittersBase extends Critters {}
93+
class BeastiesBase extends Beasties {}
9594
/* eslint-enable @typescript-eslint/no-unsafe-declaration-merging */
9695

97-
export class InlineCriticalCssProcessor extends CrittersBase {
96+
export class InlineCriticalCssProcessor extends BeastiesBase {
9897
private addedCspScriptsDocuments = new WeakSet<PartialDocument>();
9998
private documentNonces = new WeakMap<PartialDocument, string | null>();
10099

@@ -126,7 +125,7 @@ export class InlineCriticalCssProcessor extends CrittersBase {
126125
}
127126

128127
/**
129-
* Override of the Critters `embedLinkedStylesheet` method
128+
* Override of the Beasties `embedLinkedStylesheet` method
130129
* that makes it work with Angular's CSP APIs.
131130
*/
132131
override async embedLinkedStylesheet(
@@ -148,19 +147,19 @@ export class InlineCriticalCssProcessor extends CrittersBase {
148147
const cspNonce = this.findCspNonce(document);
149148

150149
if (cspNonce) {
151-
const crittersMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
150+
const beastiesMedia = link.getAttribute('onload')?.match(MEDIA_SET_HANDLER_PATTERN);
152151

153-
if (crittersMedia) {
154-
// If there's a Critters-generated `onload` handler and the file has an Angular CSP nonce,
152+
if (beastiesMedia) {
153+
// If there's a Beasties-generated `onload` handler and the file has an Angular CSP nonce,
155154
// we have to remove the handler, because it's incompatible with CSP. We save the value
156155
// in a different attribute and we generate a script tag with the nonce that uses
157156
// `addEventListener` to apply the media query instead.
158157
link.removeAttribute('onload');
159-
link.setAttribute(CSP_MEDIA_ATTR, crittersMedia[1]);
158+
link.setAttribute(CSP_MEDIA_ATTR, beastiesMedia[1]);
160159
this.conditionallyInsertCspLoadingScript(document, cspNonce, link);
161160
}
162161

163-
// Ideally we would hook in at the time Critters inserts the `style` tags, but there isn't
162+
// Ideally we would hook in at the time Beasties inserts the `style` tags, but there isn't
164163
// a way of doing that at the moment so we fall back to doing it any time a `link` tag is
165164
// inserted. We mitigate it by only iterating the direct children of the `<head>` which
166165
// should be pretty shallow.
@@ -183,7 +182,7 @@ export class InlineCriticalCssProcessor extends CrittersBase {
183182
return this.documentNonces.get(document)!;
184183
}
185184

186-
// HTML attribute are case-insensitive, but the parser used by Critters is case-sensitive.
185+
// HTML attribute are case-insensitive, but the parser used by Beasties is case-sensitive.
187186
const nonceElement = document.querySelector('[ngCspNonce], [ngcspnonce]');
188187
const cspNonce =
189188
nonceElement?.getAttribute('ngCspNonce') || nonceElement?.getAttribute('ngcspnonce') || null;

0 commit comments

Comments
 (0)