e783b0a2e8
This PR re-includes ESLint with some notable changes, namely a guided setup similar to how TypeScript is instantiated in a Next.js application. To add ESLint to a project, developers will have to create an `.eslintrc` file in the root of their project or add an empty `eslintConfig` object to their `package.json` file. ```js touch .eslintrc ``` Then running `next build` will show instructions to install the required packages needed: <img width="862" alt="Screen Shot 2021-04-19 at 7 38 27 PM" src="https://user-images.githubusercontent.com/12476932/115316182-dfd51b00-a146-11eb-830c-90bad20ed151.png"> Once installed and `next build` is run again, `.eslintrc` will be automatically configured to include the default config: ```json { "extends": "next" } ``` In addition to this change: - The feature is now under the experimental flag and requires opt-in. After testing and feedback, it will be switched to the top-level namespace and turned on by default. - A new ESLint shareable configuration package is included that can be extended in any application with `{ extends: 'next' }` - This default config extends recommended rule sets from [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react), [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks), and [`eslint-plugin-next`](https://www.npmjs.com/package/@next/eslint-plugin-next) - All rules in [`eslint-plugin-next`](https://www.npmjs.com/package/@next/eslint-plugin-next) have been modified to include actionable links that show more information to help resolve each issue
146 lines
3.1 KiB
JavaScript
146 lines
3.1 KiB
JavaScript
/* eslint-env jest */
|
|
const rule = require('@next/eslint-plugin-next/lib/rules/no-html-link-for-pages')
|
|
const { Linter } = require('eslint')
|
|
const assert = require('assert')
|
|
const path = require('path')
|
|
|
|
const linter = new Linter({ cwd: __dirname })
|
|
const linterConfig = {
|
|
rules: {
|
|
'no-html-link-for-pages': [2, path.join(__dirname, 'custom-pages')],
|
|
},
|
|
parserOptions: {
|
|
ecmaVersion: 2018,
|
|
sourceType: 'module',
|
|
ecmaFeatures: {
|
|
modules: true,
|
|
jsx: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
linter.defineRules({
|
|
'no-html-link-for-pages': rule,
|
|
})
|
|
|
|
const validCode = `
|
|
import Link from 'next/link';
|
|
|
|
export class Blah extends Head {
|
|
render() {
|
|
return (
|
|
<div>
|
|
<Link href='/'>
|
|
<a>Homepage</a>
|
|
</Link>
|
|
<h1>Hello title</h1>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
`
|
|
|
|
const validAnchorCode = `
|
|
import Link from 'next/link';
|
|
|
|
export class Blah extends Head {
|
|
render() {
|
|
return (
|
|
<div>
|
|
<a href='#heading'>Homepage</a>
|
|
<h1>Hello title</h1>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
`
|
|
|
|
const validExternalLinkCode = `
|
|
import Link from 'next/link';
|
|
|
|
export class Blah extends Head {
|
|
render() {
|
|
return (
|
|
<div>
|
|
<a href='https://google.com/'>Homepage</a>
|
|
<h1>Hello title</h1>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
`
|
|
|
|
const invalidStaticCode = `
|
|
import Link from 'next/link';
|
|
|
|
export class Blah extends Head {
|
|
render() {
|
|
return (
|
|
<div>
|
|
<a href='/'>Homepage</a>
|
|
<h1>Hello title</h1>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
`
|
|
|
|
const invalidDynamicCode = `
|
|
import Link from 'next/link';
|
|
|
|
export class Blah extends Head {
|
|
render() {
|
|
return (
|
|
<div>
|
|
<a href='/list/blah'>Homepage</a>
|
|
<h1>Hello title</h1>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
`
|
|
|
|
describe('no-html-link-for-pages', function () {
|
|
it('valid link element', function () {
|
|
const report = linter.verify(validCode, linterConfig, {
|
|
filename: 'foo.js',
|
|
})
|
|
assert.deepEqual(report, [])
|
|
})
|
|
|
|
it('valid anchor element', function () {
|
|
const report = linter.verify(validAnchorCode, linterConfig, {
|
|
filename: 'foo.js',
|
|
})
|
|
assert.deepEqual(report, [])
|
|
})
|
|
|
|
it('valid external link element', function () {
|
|
const report = linter.verify(validExternalLinkCode, linterConfig, {
|
|
filename: 'foo.js',
|
|
})
|
|
assert.deepEqual(report, [])
|
|
})
|
|
|
|
it('invalid static route', function () {
|
|
const [report] = linter.verify(invalidStaticCode, linterConfig, {
|
|
filename: 'foo.js',
|
|
})
|
|
assert.notEqual(report, undefined, 'No lint errors found.')
|
|
assert.equal(
|
|
report.message,
|
|
"Do not use the HTML <a> tag to navigate to /. Use Link from 'next/link' instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages."
|
|
)
|
|
})
|
|
|
|
it('invalid dynamic route', function () {
|
|
const [report] = linter.verify(invalidDynamicCode, linterConfig, {
|
|
filename: 'foo.js',
|
|
})
|
|
assert.notEqual(report, undefined, 'No lint errors found.')
|
|
assert.equal(
|
|
report.message,
|
|
"Do not use the HTML <a> tag to navigate to /list/blah/. Use Link from 'next/link' instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages."
|
|
)
|
|
})
|
|
})
|