forked from ricardobeat/cake-flour
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflour.coffee
165 lines (126 loc) · 4.59 KB
/
flour.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
fs = require 'fs'
path = require 'path'
util = require 'util'
domain = require 'domain'
colors = require 'colors'
mm = require 'minimatch'
File = require './lib/file'
logger = require './lib/logger'
# Main object / API
flour =
silent: (state = true) ->
logger.silent = state
compile: (file, dest, cb) ->
file.compile (output) ->
success dest, @, output, 'Compiled', cb
minify: (file, dest, cb) ->
file.minify (output) ->
success dest, @, output, 'Minified', cb
lint: (file, cb) ->
file.lint (passed, errors) ->
if passed
logger.log " OK ".green.inverse, file.path
else
logger.log " NOT OK ".magenta.inverse, file.path.bold
for e in errors when e?
pos = "[L#{e.line}:#{e.character}]"
logger.log pos.red, e.reason.grey
cb? passed, errors
bundle: (files, dest, cb) ->
unless util.isArray files
return flour.getFiles files, (results) ->
flour.bundle results, dest, cb
if files.length is 0
throw new Error 'No files match'
results = []
counter = 0
done = ->
return unless files.length is ++counter
shim = new File dest, results.join("\n")
shim.minify (output) ->
success dest, @, output, 'Packaged', cb
files.forEach (file, i) ->
file = new File file
file.compile (output) ->
results[i] = output
done()
return
watch: (file, fn) ->
file.watch fn
noConflict: ->
for m in globals
delete global[m]
if global['_'+m]? then global[m] = global['_'+m]
return
# Get a list of files from a wildcard path (*.ext)
getFiles: (filepath, cb) ->
dir = path.dirname filepath
pattern = path.basename filepath
try stats = fs.statSync filepath
if stats?.isFile()
return cb [filepath]
if stats?.isDirectory()
dir = filepath
pattern = '*.*'
fs.readdir dir, (err, results) ->
results = results.filter mm.filter pattern
results = results.map (f) -> path.join dir, f
cb results
# Get file(s)' contents
get: (filepath, cb) ->
file = new File filepath
if file.base is '*'
flour.getFiles filepath, (files) ->
results = []
count = files.length
files.forEach (f, i) ->
new File(f).read (output) ->
results[i] = output
if --count is 0 then cb results
else
file.read cb
# Load adapters
minifiers : require './adapters/minifiers'
compilers : require './adapters/compilers'
linters : require './adapters/linters'
# Success handler. Writes to file if an output path was
# provided, otherwise it just returns the result
success = (dest, file, output, action, cb) ->
# Handle callback-only calls
# flour.compile 'file', (output) ->
if typeof dest is 'function'
[cb, dest] = [dest, null]
if dest?
fs.writeFile dest, output, (err) -> cb? output
else
cb output
logger.log "#{action.magenta} #{file} @ #{new Date().toLocaleTimeString()}"
# Overwrite all methods that accept a file parameter to:
# - accept both arrays and *.xxx paths
# - capture errors using domains
# - feed the original method a File instance
['lint', 'compile', 'minify', 'watch'].forEach (method) ->
original = flour[method]
flour[method] = (file, rest...) ->
dm = domain.create()
dm.on 'error', (err) ->
logger.fail "#{method.replace(/e$/,'')}ing", file, err
if util.isArray file
dm.bind(original).apply flour, [new File f].concat(rest) for f in file
return
# Create a File object with the given path. If it turns out
# to be a wildcard path, we just discard it.
file = new File file
# Handle wildcard paths.
if file.base is '*'
flour.getFiles file.path, (files) ->
flour[method].apply flour, [files].concat(rest)
return
# Or call original method if it's a single file.
dm.bind(original).apply flour, [file].concat(rest)
# Global methods
globals = ['lint', 'compile', 'bundle', 'minify', 'watch', 'get']
for m in globals
if global[m]? then global['_'+m] = global[m]
global[m] = flour[m]
module.exports = flour