-
Notifications
You must be signed in to change notification settings - Fork 387
Expand file tree
/
Copy pathnextjs-no-google-analytics-script.ts
More file actions
38 lines (34 loc) · 1.57 KB
/
nextjs-no-google-analytics-script.ts
File metadata and controls
38 lines (34 loc) · 1.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { GOOGLE_ANALYTICS_SCRIPT_PATTERN } from "../../constants/nextjs.js";
import { defineRule } from "../../utils/define-rule.js";
import { findJsxAttribute } from "../../utils/find-jsx-attribute.js";
import type { Rule } from "../../utils/rule.js";
import type { RuleContext } from "../../utils/rule-context.js";
import { isNodeOfType } from "../../utils/is-node-of-type.js";
import type { EsTreeNodeOfType } from "../../utils/es-tree-node-of-type.js";
export const nextjsNoGoogleAnalyticsScript = defineRule<Rule>({
id: "nextjs-no-google-analytics-script",
title: "Manual Google Analytics script",
tags: ["test-noise"],
requires: ["nextjs"],
severity: "warn",
recommendation:
"Use `import { GoogleAnalytics } from '@next/third-parties/google'` for automatic optimization & smaller bundles",
create: (context: RuleContext) => ({
JSXOpeningElement(node: EsTreeNodeOfType<"JSXOpeningElement">) {
if (!isNodeOfType(node.name, "JSXIdentifier")) return;
if (node.name.name !== "script" && node.name.name !== "Script") return;
const srcAttribute = findJsxAttribute(node.attributes ?? [], "src");
if (!srcAttribute?.value) return;
const srcValue = isNodeOfType(srcAttribute.value, "Literal")
? srcAttribute.value.value
: null;
if (typeof srcValue === "string" && GOOGLE_ANALYTICS_SCRIPT_PATTERN.test(srcValue)) {
context.report({
node,
message:
"Manual Google Analytics script blocks rendering — @next/third-parties loads it with optimal strategy.",
});
}
},
}),
});