-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.coffee
133 lines (103 loc) · 3.36 KB
/
index.coffee
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
131
132
133
path = require('path')
fs = require('fs')
util = require('util')
events = require('events')
_ = require('underscore')
walkdir = require('walkdir')
index = (opts) ->
# Collect arguments.. can be in various formats
if not _.isObject(opts) then opts = { dir: dir }
_.defaults opts,
basedir: './'
dir: './'
extensions: ['.sass','.scss']
ignore: [
]
# Add ignore paths that can't be overwrited
opts = _.extend opts,
ignore: _.uniq(opts.ignore.concat([
'**/.DS_Store',
'**/index.sass',
'**/index.scss',
'**/_index.sass',
'**/_index.scss'
]))
opts.dir = dir = path.resolve(opts.basedir,opts.dir)
# Resolve ignore paths to opts.basedir
opts.ignore = opts.ignore.map (dir) ->
return path.resolve(opts.basedir,dir)
# Start searching for files
walker = walkdir(dir)
walker.on 'directory', (dir) ->
return if shouldIgnorePath(dir)
writeIndexFor(dir)
# Check if file is marked as a path to ignore
indexignore_cache = {}
shouldIgnorePath = (file,stat=null) ->
path = require('path')
fs = require('fs')
minimatch = require('minimatch')
ignore_globs = opts.ignore
unless stat?
stat = fs.statSync(file)
if stat.isDirectory()
dir = file
else
dir = path.dirname(file)
# Merge in entries from the .indexignore file if it exists
if not _.has(indexignore_cache,dir)
try
indexignore_contents = fs.readFileSync(path.join(dir,'.indexignore'))
catch
indexignore_contents = null
if indexignore_contents instanceof Buffer
new_ignore_list = indexignore_contents.toString().split(/[\r|\n]/)
new_ignore_list = _.filter(new_ignore_list, (subpath) => not _.isEmpty(subpath))
ignore_globs = ignore_globs.concat(new_ignore_list.map((subfile) => path.resolve(dir,subfile)))
indexignore_cache[dir] = ignore_globs
else
ignore_globs = indexignore_cache[dir]
# Now loop through ignore globs and check if the path matches any of them..
# Checks for directories or files, see
# https://github.com/EE/gitignore-to-glob/blob/master/lib/gitignore-to-glob.js#L53
for ignore_glob in ignore_globs
if minimatch(file, ignore_glob) or minimatch(file, ignore_glob + '/**')
return true
return false
# Write the SASS index file for a directory
writeIndexFor = (dir) =>
files = []
if fs.existsSync(path.join(dir,'.indexkeep'))
return false
walkdir.sync dir, no_recurse: true, (file,stat) ->
relative = path.relative(dir,file)
importName = './' + relative
if not shouldIgnorePath(file,stat)
if stat.isDirectory()
files.push('./' + importName + '/index')
else
ext = path.extname(file)
if (ext in opts.extensions)
files.push('./' + importName.slice(0,ext.length * -1))
if files.length is 0 then return false
# Write the SASS file
output = ""
for file in files
file = file.replace(/^\.\/\.\//,'./')
output += """@import "#{file}"\n"""
output = output.trim()
if fs.existsSync(path.resolve(dir,"./_index.sass"))
outputFile = path.resolve(dir,"./_index.sass")
else
outputFile = path.resolve(dir,"./index.sass")
fs.writeFileSync(outputFile,output)
this.emit("data", outputFile, output)
walker.on 'end', =>
# Write an index for the root dir.
writeIndexFor(opts.dir)
# And then return
this.emit("end")
return events.EventEmitter.call(this)
# Return instance on include
util.inherits(index,events.EventEmitter)
module.exports = -> new index(arguments...)