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 ) ]
2016-05-04 08:43:40 +08:00
lookupPath = " #{ path . dirname ( f ) } / #{ 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 )
2016-05-04 08:43:40 +08:00
esExportDefault [ lookupPath ] = true
2016-05-04 08:24:11 +08:00
else
2016-05-04 08:43:40 +08:00
esExport [ lookupPath ] = true
2016-05-04 08:24:11 +08:00
else
2016-05-04 08:43:40 +08:00
esNoExport [ lookupPath ] = true
2016-05-04 08:24:11 +08:00
2016-05-04 08:43:40 +08:00
# 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
2016-05-04 08:43:40 +08:00
if requirePath [ 0 ] is " . "
lookupPath = path . normalize ( path . join ( path . dirname ( f ) , requirePath ) )
else
lookupPath = requirePath
2016-05-04 08:24:11 +08:00
baseRequirePath = path . basename ( requirePath )
plainRequireRe = new RegExp ( " require[ (][ ' \" ].* #{ baseRequirePath } [ ' \" ] \\ )?$ " , " gm " )
defaultRequireRe = new RegExp ( " require \\ ([ ' \" ].* #{ baseRequirePath } [ ' \" ] \\ ) \\ .default " , " gm " )
2016-05-04 08:43:40 +08:00
if esExport [ lookupPath ]
2016-05-04 08:24:11 +08:00
if not plainRequireRe . test ( content )
errors . push ( " #{ f } : ES6 no `default` exported #{ requirePath } " )
2016-05-04 08:43:40 +08:00
else if esNoExport [ lookupPath ]
2016-05-04 08:24:11 +08:00
errors . push ( " #{ f } : nothing exported from #{ requirePath } " )
2016-05-04 08:43:40 +08:00
else if esExportDefault [ lookupPath ]
2016-05-04 08:24:11 +08:00
if not defaultRequireRe . test ( content )
errors . push ( " #{ f } : ES6 add `default` to require #{ requirePath } " )
2016-05-04 06:42:13 +08:00
2016-05-04 08:43:40 +08:00
else
# must be a coffeescript or core file
if defaultRequireRe . test ( content )
errors . push ( " #{ f } : don ' t ask for `default` from #{ 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 )