UNPKG

3.58 kBtext/coffeescriptView Raw
1fs = require 'fs'
2mkdirp = require 'mkdirp'
3async = require 'async'
4stylus = require 'stylus'
5{compile} = require './compiler'
6
7class OnTheFlyCompiler
8 constructor: (js, css, compilers) ->
9 @js = js
10 @css = css
11 @compilers = compilers
12
13 setImportFlag = (files) ->
14 for file in files
15 file._importChecked = false
16
17 setImportFlag(@js.files)
18 setImportFlag(@css.files)
19
20 middleware: (req, res, next) =>
21 if req.url.indexOf('.js') > -1
22 for file, i in @js.files
23 if req.url == file.url
24 return @handleFile(file, -> next())
25 else
26 return next() if i == (@js.files.length - 1)
27
28 else if req.url.indexOf('.css') > -1
29 for file, i in @css.files
30 if req.url == file.url
31 return @handleFile(file, -> next()) if req.url == file.url
32 else
33 return next() if i == (@css.files.length - 1)
34 return next()
35
36 handleFile: (file, fn) =>
37 if not file._importChecked
38 @mapImports file, =>
39 file._importChecked = true
40 return @handleFile(file, fn)
41 return
42
43 # Check modified timestamp on file
44 fs.stat file.origFile, (err, destStats) =>
45 if not file._mtime
46 return @compileFile(file, fn)
47 if file._mtime < destStats.mtime
48 return @compileFile(file, fn)
49
50 # Check modified timestamps on imports
51 else if file._imports?
52 changed = []
53 compileFile = @compileFile
54 async.forEach(file._imports, (importedFile, cb) =>
55 fs.stat importedFile.file, (err, stats) =>
56 return cb(err) if err?
57 # One of the imported files changed
58 if importedFile.mtime < stats.mtime
59 importedFile.mtime = stats.mtime
60 changed.push importedFile
61 return cb()
62 , ->
63 if changed.length > 0
64 return compileFile(file, fn)
65 else
66 return fn()
67 )
68 else
69 fn()
70
71 compileFile: (file, fn) =>
72 return fn() unless file.needsCompiling
73
74 fs.readFile file.origFile, 'utf8', (err, content) =>
75 compile @compilers, content, file.origFile, (err, newContent) =>
76 @writeToFile file.file, newContent, ->
77 fs.stat file.origFile, (err, stats) ->
78 file._mtime = stats.mtime
79 return fn()
80
81 writeToFile: (file, content, fn) =>
82 fs.writeFile file, content, 'utf8', (err) =>
83 if err
84 if err.code == 'ENOENT'
85 splitted = file.split('/')
86 mkdirp splitted.splice(0, splitted.length-1).join('/'), 0777, (err) =>
87 if err?
88 console.log err
89 else
90 return @writeToFile(file, content, fn)
91 else
92 console.log err
93 else
94 return fn()
95
96 mapImports: (file, fn) ->
97 # Need to map imports for stylus files
98 if file.origFile.indexOf('.styl') > -1
99 fs.readFile file.origFile, 'utf8', (err, content) =>
100 console.log err if err?
101 style = @compilers.stylus(content, file.origFile)
102 file._imports = []
103 paths = style.options._imports = []
104 style.render (err, css) ->
105 console.log err if err?
106 async.forEach(paths, (path, cb) ->
107 if path.path
108 fs.stat path.path, (err, stats) ->
109 console.log if err?
110 file._imports.push
111 file: path.path
112 mtime: stats.mtime
113 cb()
114 else
115 cb()
116 , ->
117 return fn()
118 )
119 else
120 return fn()
121
122module.exports = OnTheFlyCompiler