This repository has been archived by the owner on Jun 21, 2023. It is now read-only.
forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ESLint Plugin: Disallow <title> in Head from next/document (vercel#24868
) Adds lint rule warning to the Next.js ESLint plugin to disallow `<title>` in `Head` imported from `next/document`.
- Loading branch information
1 parent
b2ba983
commit 06d16a3
Showing
5 changed files
with
154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# No Title in Document Head | ||
|
||
### Why This Error Occurred | ||
|
||
A `<title>` element was defined within the `Head` component imported from `next/document`, which should only be used for any `<head>` code that is common for all pages. Title tags should be defined at the page-level using `next/head`. | ||
|
||
### Possible Ways to Fix It | ||
|
||
Within a page or component, import and use `next/head` to define a page title: | ||
|
||
```jsx | ||
import Head from 'next/head' | ||
|
||
export class Home { | ||
render() { | ||
return ( | ||
<div> | ||
<Head> | ||
<title>My page title</title> | ||
</Head> | ||
</div> | ||
) | ||
} | ||
} | ||
``` | ||
|
||
### Useful links | ||
|
||
- [next/head](https://nextjs.org/docs/api-reference/next/head) | ||
- [Custom Document](https://nextjs.org/docs/advanced-features/custom-document) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
packages/eslint-plugin-next/lib/rules/no-title-in-document-head.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Disallow using <title> with Head from next/document', | ||
}, | ||
}, | ||
create: function (context) { | ||
let headFromNextDocument = false | ||
return { | ||
ImportDeclaration(node) { | ||
if (node.source.value === 'next/document') { | ||
if (node.specifiers.some(({ local }) => local.name === 'Head')) { | ||
headFromNextDocument = true | ||
} | ||
} | ||
}, | ||
JSXElement(node) { | ||
if (!headFromNextDocument) { | ||
return | ||
} | ||
|
||
if ( | ||
node.openingElement && | ||
node.openingElement.name && | ||
node.openingElement.name.name !== 'Head' | ||
) { | ||
return | ||
} | ||
|
||
const titleTag = node.children.find( | ||
(child) => | ||
child.openingElement && | ||
child.openingElement.name && | ||
child.openingElement.name.type === 'JSXIdentifier' && | ||
child.openingElement.name.name === 'title' | ||
) | ||
|
||
if (titleTag) { | ||
context.report({ | ||
node: titleTag, | ||
message: | ||
'Titles should be defined at the page-level using next/head. See https://nextjs.org/docs/messages/no-title-in-document-head.', | ||
}) | ||
} | ||
}, | ||
} | ||
}, | ||
} |
70 changes: 70 additions & 0 deletions
70
test/eslint-plugin-next/no-title-in-document-head.unit.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
const rule = require('@next/eslint-plugin-next/lib/rules/no-title-in-document-head') | ||
const RuleTester = require('eslint').RuleTester | ||
|
||
RuleTester.setDefaultConfig({ | ||
parserOptions: { | ||
ecmaVersion: 2018, | ||
sourceType: 'module', | ||
ecmaFeatures: { | ||
modules: true, | ||
jsx: true, | ||
}, | ||
}, | ||
}) | ||
|
||
var ruleTester = new RuleTester() | ||
ruleTester.run('no-title-in-document-head', rule, { | ||
valid: [ | ||
`import Head from "next/head"; | ||
class Test { | ||
render() { | ||
return ( | ||
<Head> | ||
<title>My page title</title> | ||
</Head> | ||
); | ||
} | ||
}`, | ||
|
||
`import Document, { Html, Head } from "next/document"; | ||
class MyDocument extends Document { | ||
render() { | ||
return ( | ||
<Html> | ||
<Head> | ||
</Head> | ||
</Html> | ||
); | ||
} | ||
} | ||
export default MyDocument; | ||
`, | ||
], | ||
|
||
invalid: [ | ||
{ | ||
code: ` | ||
import { Head } from "next/document"; | ||
class Test { | ||
render() { | ||
return ( | ||
<Head> | ||
<title>My page title</title> | ||
</Head> | ||
); | ||
} | ||
}`, | ||
errors: [ | ||
{ | ||
message: | ||
'Titles should be defined at the page-level using next/head. See https://nextjs.org/docs/messages/no-title-in-document-head.', | ||
type: 'JSXElement', | ||
}, | ||
], | ||
}, | ||
], | ||
}) |