forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
no-unwanted-polyfillio.js
130 lines (125 loc) · 3.7 KB
/
no-unwanted-polyfillio.js
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
const NEXT_POLYFILLED_FEATURES = [
'Array.prototype.@@iterator',
'Array.prototype.copyWithin',
'Array.prototype.fill',
'Array.prototype.find',
'Array.prototype.findIndex',
'Array.prototype.flatMap',
'Array.prototype.flat',
'Array.from',
'Array.prototype.includes',
'Array.of',
'Function.prototype.name',
'fetch',
'Map',
'Number.EPSILON',
'Number.Epsilon',
'Number.isFinite',
'Number.isNaN',
'Number.isInteger',
'Number.isSafeInteger',
'Number.MAX_SAFE_INTEGER',
'Number.MIN_SAFE_INTEGER',
'Object.entries',
'Object.getOwnPropertyDescriptor',
'Object.getOwnPropertyDescriptors',
'Object.is',
'Object.keys',
'Object.values',
'Reflect',
'Set',
'Symbol',
'Symbol.asyncIterator',
'String.prototype.codePointAt',
'String.prototype.endsWith',
'String.fromCodePoint',
'String.prototype.includes',
'String.prototype.@@iterator',
'String.prototype.padEnd',
'String.prototype.padStart',
'String.prototype.repeat',
'String.raw',
'String.prototype.startsWith',
'String.prototype.trimEnd',
'String.prototype.trimStart',
'String.prototype.trim',
'URL',
'URLSearchParams',
'WeakMap',
'WeakSet',
'Promise',
'Promise.prototype.finally',
'es2015', // Should be covered by babel-preset-env instead.
'es2016', // Should be covered by babel-preset-env instead.
'es2017', // Should be covered by babel-preset-env instead.
'es2018', // Should be covered by babel-preset-env instead.
'es2019', // Should be covered by babel-preset-env instead.
'es5', // Should be covered by babel-preset-env instead.
'es6', // Should be covered by babel-preset-env instead.
'es7', // Should be covered by babel-preset-env instead.
]
const url = 'https://nextjs.org/docs/messages/no-unwanted-polyfillio'
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
docs: {
description: 'Prevent duplicate polyfills from Polyfill.io.',
category: 'HTML',
recommended: true,
url,
},
type: 'problem',
schema: [],
},
create: function (context) {
let scriptImport = null
return {
ImportDeclaration(node) {
if (node.source && node.source.value === 'next/script') {
scriptImport = node.specifiers[0].local.name
}
},
JSXOpeningElement(node) {
if (
node.name &&
node.name.name !== 'script' &&
node.name.name !== scriptImport
) {
return
}
if (node.attributes.length === 0) {
return
}
const srcNode = node.attributes.find(
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'src'
)
if (!srcNode || srcNode.value.type !== 'Literal') {
return
}
const src = srcNode.value.value
if (
src.startsWith('https://cdn.polyfill.io/v2/') ||
src.startsWith('https://polyfill.io/v3/')
) {
const featureQueryString = new URL(src).searchParams.get('features')
const featuresRequested = (featureQueryString || '').split(',')
const unwantedFeatures = featuresRequested.filter((feature) =>
NEXT_POLYFILLED_FEATURES.includes(feature)
)
if (unwantedFeatures.length > 0) {
context.report({
node,
message: `No duplicate polyfills from Polyfill.io are allowed. ${unwantedFeatures.join(
', '
)} ${
unwantedFeatures.length > 1 ? 'are' : 'is'
} already shipped with Next.js. See: ${url}`,
})
}
}
},
}
},
}