fix(eslint): next/script beforeInteractive gives warning on appDir (#51148)

## Issue

The `context.getFilename()` gets the absolute path of the files, and the if statement to filter `/src` and `/app` was not working since #46609.

## Expected

Do not show a lint warning if use `beforeInteractive` inside `appDir`.

Fixes #46609 #50261
This commit is contained in:
Jiwon Choi 2023-11-12 18:30:10 +09:00 committed by GitHub
parent a794e1f32e
commit 022cb25640
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 121 additions and 61 deletions

View file

@ -4,10 +4,8 @@ import * as path from 'path'
const url =
'https://nextjs.org/docs/messages/no-before-interactive-script-outside-document'
const startsWithUsingCorrectSeparators = (str: string, start: string) =>
[path.sep, path.posix.sep].some((sep) =>
str.startsWith(start.replace(/\//g, sep))
)
const convertToCorrectSeparator = (str: string) =>
str.replace(/[\\/]/g, path.sep)
export = defineRule({
meta: {
@ -25,24 +23,17 @@ export = defineRule({
return {
'ImportDeclaration[source.value="next/script"] > ImportDefaultSpecifier'(
node
node: any
) {
scriptImportName = node.local.name
},
JSXOpeningElement(node) {
let pathname = context.getFilename()
const pathname = convertToCorrectSeparator(context.getFilename())
if (startsWithUsingCorrectSeparators(pathname, 'src/')) {
pathname = pathname.slice(4)
} else if (startsWithUsingCorrectSeparators(pathname, '/src/')) {
pathname = pathname.slice(5)
}
const isInAppDir = pathname.includes(`${path.sep}app${path.sep}`)
// This rule shouldn't fire in `app/`
if (
startsWithUsingCorrectSeparators(pathname, 'app/') ||
startsWithUsingCorrectSeparators(pathname, '/app/')
) {
if (isInAppDir) {
return
}

View file

@ -109,59 +109,33 @@ ruleTester.run('no-before-interactive-script-outside-document', rule, {
export default function Index() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: 'app/deep/root/layout.tsx',
filename: '/Users/user_name/projects/project-name/app/layout.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
export default function test() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: 'app/deep/page.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
);
}`,
filename: 'app/deep/randomFile.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
);
}`,
filename: 'src/app/deep/randomFile.tsx',
filename: 'C:\\Users\\username\\projects\\project-name\\app\\layout.tsx',
},
{
code: `
@ -178,13 +152,13 @@ ruleTester.run('no-before-interactive-script-outside-document', rule, {
</html>
);
}`,
filename: '/src/app/layout.tsx',
filename: '/Users/user_name/projects/project-name/src/app/layout.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
export default function test() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
@ -195,7 +169,8 @@ ruleTester.run('no-before-interactive-script-outside-document', rule, {
</html>
);
}`,
filename: '/app/layout.tsx',
filename:
'C:\\Users\\username\\projects\\project-name\\src\\app\\layout.tsx',
},
].map((obj, idx) => ({
...obj,
@ -249,6 +224,100 @@ ruleTester.run('no-before-interactive-script-outside-document', rule, {
},
],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/pages/layout.tsx',
errors: [
{
message:
"`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: https://nextjs.org/docs/messages/no-before-interactive-script-outside-document",
},
],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename:
'C:\\Users\\username\\projects\\project-name\\pages\\layout.tsx',
errors: [
{
message:
"`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: https://nextjs.org/docs/messages/no-before-interactive-script-outside-document",
},
],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/src/pages/layout.tsx',
errors: [
{
message:
"`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: https://nextjs.org/docs/messages/no-before-interactive-script-outside-document",
},
],
},
{
code: `
import Script from "next/script";
export default function test() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename:
'C:\\Users\\username\\projects\\project-name\\src\\pages\\layout.tsx',
errors: [
{
message:
"`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: https://nextjs.org/docs/messages/no-before-interactive-script-outside-document",
},
],
},
].map((obj, idx) => ({
...obj,
code: `// invalid-${idx}