Skip to content

Commit

Permalink
Experimental: New ESLint Plugin (#11986)
Browse files Browse the repository at this point in the history
  • Loading branch information
janicklas-ralph authored May 7, 2020
1 parent a795e48 commit 5ad512b
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/eslint-plugin-next/lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
rules: {
'no-css-tags': require('./rules/no-css-tags'),
'no-sync-scripts': require('./rules/no-sync-scripts'),
},
configs: {
recommended: {
rules: {
'@next/next/no-css-tags': 1,
'@next/next/no-sync-scripts': 1,
},
},
},
}
29 changes: 29 additions & 0 deletions packages/eslint-plugin-next/lib/rules/no-css-tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module.exports = function(context) {
return {
JSXOpeningElement(node) {
if (node.name.name !== 'link') {
return
}
if (node.attributes.length === 0) {
return
}

if (
node.attributes.find(
attr => attr.name.name === 'rel' && attr.value.value === 'stylesheet'
) &&
node.attributes.find(
attr => attr.name.name === 'href' && !/^https?/.test(attr.value.value)
)
) {
context.report({
node,
message:
'In order to use external stylesheets use @import in the root stylesheet compiled with NextJS. This ensures proper priority to CSS when loading a webpage.',
})
}
},
}
}

module.exports.schema = []
27 changes: 27 additions & 0 deletions packages/eslint-plugin-next/lib/rules/no-sync-scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module.exports = function(context) {
return {
JSXOpeningElement(node) {
if (node.name.name !== 'script') {
return
}
if (node.attributes.length === 0) {
return
}

if (
node.attributes.find(attr => attr.name.name === 'src') &&
!node.attributes.find(
attr => attr.name.name === 'async' || attr.name.name === 'defer'
)
) {
context.report({
node,
message:
"A synchronous script tag can impact your webpage's performance",
})
}
},
}
}

module.exports.schema = []
11 changes: 11 additions & 0 deletions packages/eslint-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@next/eslint-plugin-next",
"version": "0.0.0",
"description": "ESLint plugin for NextJS.",
"main": "lib/index.js",
"license": "MIT",
"repository": {
"url": "zeit/next.js",
"directory": "packages/eslint-plugin-next"
}
}
80 changes: 80 additions & 0 deletions test/eslint-plugin-next/no-css-tags.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const rule = require('@next/eslint-plugin-next/lib/rules/no-css-tags')
const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
modules: true,
jsx: true,
},
},
})

var ruleTester = new RuleTester()
ruleTester.run('no-css-tags', rule, {
valid: [
`import {Head} from 'next/document';
export class Blah extends Head {
render() {
return (
<div>
<h1>Hello title</h1>
</div>
);
}
}`,

`import {Head} from 'next/document';
export class Blah extends Head {
render() {
return (
<div>
<h1>Hello title</h1>
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet" />
</div>
);
}
}`,
],

invalid: [
{
code: `
import {Head} from 'next/document';
export class Blah extends Head {
render() {
return (
<div>
<h1>Hello title</h1>
<link href="/_next/static/css/styles.css" rel="stylesheet" />
</div>
);
}
}`,
errors: [
{
message:
'In order to use external stylesheets use @import in the root stylesheet compiled with NextJS. This ensures proper priority to CSS when loading a webpage.',
type: 'JSXOpeningElement',
},
],
},
{
code: `
<div>
<link href="/_next/static/css/styles.css" rel="stylesheet" />
</div>`,
errors: [
{
message:
'In order to use external stylesheets use @import in the root stylesheet compiled with NextJS. This ensures proper priority to CSS when loading a webpage.',
type: 'JSXOpeningElement',
},
],
},
],
})
57 changes: 57 additions & 0 deletions test/eslint-plugin-next/no-sync-scripts.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const rule = require('@next/eslint-plugin-next/lib/rules/no-sync-scripts')

const RuleTester = require('eslint').RuleTester

RuleTester.setDefaultConfig({
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
modules: true,
jsx: true,
},
},
})

var ruleTester = new RuleTester()
ruleTester.run('sync-scripts', rule, {
valid: [
`import {Head} from 'next/document';
export class Blah extends Head {
render() {
return (
<div>
<h1>Hello title</h1>
<script src='https://blah.com' async></script>
</div>
);
}
}`,
],

invalid: [
{
code: `
import {Head} from 'next/document';
export class Blah extends Head {
render() {
return (
<div>
<h1>Hello title</h1>
<script src='https://blah.com'></script>
</div>
);
}
}`,
errors: [
{
message:
"A synchronous script tag can impact your webpage's performance",
type: 'JSXOpeningElement',
},
],
},
],
})

0 comments on commit 5ad512b

Please sign in to comment.