2015-07-20 01:56:24 +08:00
path = require ' path '
fs = require ' fs-plus '
module.exports = (grunt) ->
grunt . registerMultiTask ' nylaslint ' , ' Check requires for file extensions compiled away ' , ->
done = @ async ( )
2016-05-04 06:42:13 +08:00
extensionRegex = /require ['"].*\.(coffee|cjsx|jsx|es6|es)['"]/i
2015-07-20 01:56:24 +08:00
for fileset in @ files
grunt . log . writeln ( ' Nylinting ' + fileset . src . length + ' files. ' )
2016-05-04 06:42:13 +08:00
esExtensions = {
" .es6 " : true
" .es " : true
" .jsx " : true
}
coffeeExtensions = {
" .coffee " : true
" .cjsx " : true
}
2016-05-04 08:24:11 +08:00
errors = [ ]
esExport = { }
esNoExport = { }
esExportDefault = { }
2016-05-04 06:42:13 +08:00
for f in fileset . src
2016-05-04 08:24:11 +08:00
continue if not esExtensions [ path . extname ( f ) ]
fname = path . basename ( f , path . extname ( f ) )
2016-05-04 06:42:13 +08:00
2016-05-04 08:24:11 +08:00
content = fs . readFileSync ( f , encoding : ' utf8 ' )
if /module.exports\s?=\s?.+/gmi . test ( content )
errors . push ( " #{ f } : Don ' t use module.exports in ES6 " )
if /^export/gmi . test ( content )
if /^export\ default/gmi . test ( content )
esExportDefault [ fname ] = true
else
esExport [ fname ] = true
else
esNoExport [ fname ] = true
blacklist = [ " events " , " main " , " package " , " task " ]
for item in blacklist
delete esExportDefault [ item ]
delete esExport [ item ]
delete esNoExport [ item ]
2016-05-04 06:42:13 +08:00
2015-07-20 01:56:24 +08:00
# file.src is the list of all matching file names.
for f in fileset . src
2016-05-04 08:24:11 +08:00
continue if esExtensions [ path . extname ( f ) ]
content = fs . readFileSync ( f , encoding : ' utf8 ' )
if extensionRegex . test ( content )
errors . push ( " #{ f } : Remove require extension! " )
requireRe = /require[ (]['"]([\w_./-]*?)['"]/gmi
while result = requireRe . exec ( content )
i = 1
while i < result . length
requirePath = result [ i ]
i += 1
baseRequirePath = path . basename ( requirePath )
plainRequireRe = new RegExp ( " require[ (][ ' \" ].* #{ baseRequirePath } [ ' \" ] \\ )?$ " , " gm " )
defaultRequireRe = new RegExp ( " require \\ ([ ' \" ].* #{ baseRequirePath } [ ' \" ] \\ ) \\ .default " , " gm " )
if esExport [ baseRequirePath ]
if not plainRequireRe . test ( content )
errors . push ( " #{ f } : ES6 no `default` exported #{ requirePath } " )
if esNoExport [ baseRequirePath ]
errors . push ( " #{ f } : nothing exported from #{ requirePath } " )
if esExportDefault [ baseRequirePath ]
if not defaultRequireRe . test ( content )
errors . push ( " #{ f } : ES6 add `default` to require #{ requirePath } " )
2016-05-04 06:42:13 +08:00
if errors . length > 0
grunt . log . error ( err ) for err in errors
2016-05-04 07:42:28 +08:00
done ( new Error ( " Please fix the #{ errors . length } linter errors! Since we compile files in production to plain `.js` files it ' s very important you do NOT include the file extension when `require`ing a file. Also, as of Babel 6, `require` no longer returns whatever the `default` value is. If you are `require`ing an es6 file from a coffeescript file, you must explicitly request the `default` property. For example: do `require( ' ./my-es6-file ' ).default` " ) )
2015-07-20 01:56:24 +08:00
2015-08-29 02:12:53 +08:00
done ( null )