Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dynamic-import-chunkname): Add proper webpack comment parsing #1163

Merged
merged 1 commit into from
Aug 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/rules/dynamic-import-chunkname.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import(
/*webpackChunkName:"someModule"*/
'someModule',
);
import(
/* webpackChunkName : "someModule" */
'someModule',
);

// chunkname contains a 6 (forbidden by rule config)
import(
Expand All @@ -41,6 +45,12 @@ import(
'someModule',
);

// invalid syntax for webpack comment
import(
/* totally not webpackChunkName: "someModule" */
'someModule',
);

// single-line comment, not a block-style comment
import(
// webpackChunkName: "someModule"
Expand All @@ -59,6 +69,15 @@ The following patterns are valid:
/* webpackChunkName: "someOtherModule12345789" */
'someModule',
);
import(
/* webpackChunkName: "someModule" */
/* webpackPrefetch: true */
'someModule',
);
import(
/* webpackChunkName: "someModule", webpackPrefetch: true */
'someModule',
);
```

## When Not To Use It
Expand Down
65 changes: 52 additions & 13 deletions src/rules/dynamic-import-chunkname.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import vm from 'vm'
import docsUrl from '../docsUrl'

module.exports = {
Expand Down Expand Up @@ -27,8 +28,10 @@ module.exports = {
const { importFunctions = [] } = config || {}
const { webpackChunknameFormat = '[0-9a-zA-Z-_/.]+' } = config || {}

const commentFormat = ` webpackChunkName: "${webpackChunknameFormat}" `
const commentRegex = new RegExp(commentFormat)
const paddedCommentRegex = /^ (\S[\s\S]+\S) $/
const commentStyleRegex = /^( \w+: ("[^"]*"|\d+|false|true),?)+ $/
const chunkSubstrFormat = ` webpackChunkName: "${webpackChunknameFormat}",? `
const chunkSubstrRegex = new RegExp(chunkSubstrFormat)

return {
CallExpression(node) {
Expand All @@ -40,28 +43,64 @@ module.exports = {
const arg = node.arguments[0]
const leadingComments = sourceCode.getComments(arg).leading

if (!leadingComments || leadingComments.length !== 1) {
if (!leadingComments || leadingComments.length === 0) {
context.report({
node,
message: 'dynamic imports require a leading comment with the webpack chunkname',
})
return
}

const comment = leadingComments[0]
if (comment.type !== 'Block') {
context.report({
node,
message: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
})
return
let isChunknamePresent = false

for (const comment of leadingComments) {
if (comment.type !== 'Block') {
context.report({
node,
message: 'dynamic imports require a /* foo */ style comment, not a // foo comment',
})
return
}

if (!paddedCommentRegex.test(comment.value)) {
context.report({
node,
message: `dynamic imports require a block comment padded with spaces - /* foo */`,
})
return
}

try {
// just like webpack itself does
vm.runInNewContext(`(function(){return {${comment.value}}})()`)
}
catch (error) {
context.report({
node,
message: `dynamic imports require a "webpack" comment with valid syntax`,
})
return
}

if (!commentStyleRegex.test(comment.value)) {
context.report({
node,
message:
`dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
})
return
}

if (chunkSubstrRegex.test(comment.value)) {
isChunknamePresent = true
}
}

const webpackChunkDefinition = comment.value
if (!webpackChunkDefinition.match(commentRegex)) {
if (!isChunknamePresent) {
context.report({
node,
message: `dynamic imports require a leading comment in the form /*${commentFormat}*/`,
message:
`dynamic imports require a leading comment in the form /*${chunkSubstrFormat}*/`,
})
}
},
Expand Down
141 changes: 133 additions & 8 deletions tests/src/rules/dynamic-import-chunkname.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ const parser = 'babel-eslint'

const noLeadingCommentError = 'dynamic imports require a leading comment with the webpack chunkname'
const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment, not a // foo comment'
const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${commentFormat}" */`
const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${pickyCommentFormat}" */`
const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */'
const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax'
const commentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${commentFormat}",? */`
const pickyCommentFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: "${pickyCommentFormat}",? */`

ruleTester.run('dynamic-import-chunkname', rule, {
valid: [
Expand Down Expand Up @@ -79,6 +81,56 @@ ruleTester.run('dynamic-import-chunkname', rule, {
options,
parser,
},
{
code: `import(
/* webpackChunkName: "someModule", webpackPrefetch: true */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackChunkName: "someModule", webpackPrefetch: true, */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackPrefetch: true, webpackChunkName: "someModule" */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackPrefetch: true, webpackChunkName: "someModule", */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackPrefetch: true */
/* webpackChunkName: "someModule" */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackChunkName: "someModule" */
/* webpackPrefetch: true */
'test'
)`,
options,
parser,
},
{
code: `import(
/* webpackChunkName: "someModule" */
Expand Down Expand Up @@ -124,7 +176,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
options,
parser,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand All @@ -148,7 +200,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
options,
parser,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand All @@ -164,6 +216,79 @@ ruleTester.run('dynamic-import-chunkname', rule, {
type: 'CallExpression',
}],
},
{
code: `import(
/*webpackChunkName: "someModule"*/
'someModule'
)`,
options,
parser,
errors: [{
message: noPaddingCommentError,
type: 'CallExpression',
}],
},
{
code: `import(
/* webpackChunkName : "someModule" */
'someModule'
)`,
options,
parser,
errors: [{
message: commentFormatError,
type: 'CallExpression',
}],
},
{
code: `import(
/* webpackChunkName: "someModule" ; */
'someModule'
)`,
options,
parser,
errors: [{
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
{
code: `import(
/* totally not webpackChunkName: "someModule" */
'someModule'
)`,
options,
parser,
errors: [{
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
{
code: `import(
/* webpackPrefetch: true */
/* webpackChunk: "someModule" */
'someModule'
)`,
options,
parser,
errors: [{
message: commentFormatError,
type: 'CallExpression',
}],
},
{
code: `import(
/* webpackPrefetch: true, webpackChunk: "someModule" */
'someModule'
)`,
options,
parser,
errors: [{
message: commentFormatError,
type: 'CallExpression',
}],
},
{
code: `import(
/* webpackChunkName: "someModule123" */
Expand All @@ -183,7 +308,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
)`,
options: multipleImportFunctionOptions,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand All @@ -194,7 +319,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
)`,
options: multipleImportFunctionOptions,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand Down Expand Up @@ -224,7 +349,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
)`,
options,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand All @@ -246,7 +371,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
)`,
options,
errors: [{
message: commentFormatError,
message: invalidSyntaxCommentError,
type: 'CallExpression',
}],
},
Expand Down