UNPKG

4.32 kBtext/coffeescriptView Raw
1crypto = require 'crypto'
2path = require 'path'
3compiler = require './compiler'
4fs = require 'fs'
5{writeToFile, normalizeUrl} = require './helpers'
6
7class Bundle
8 constructor: (@options) ->
9 @options.staticRoot = path.normalize(@options.staticRoot)
10 @files = []
11 @defaultNamespace = 'global'
12
13 # Gets relative path from staticRoot. If the
14 # file passed in resides in another folder
15 # the path returned is relative to the
16 # root of the application
17 _getRelativePath: (file) =>
18 relativePath = ''
19 for char, i in file
20 if @options.staticRoot[i] == file[i]
21 continue
22 else
23 relativePath = file.substring(i)
24 break
25 return relativePath
26
27 #
28 # Determines based on file extension
29 # if the file needs to get compiled
30 #
31 _needsCompiling: (file) ->
32 fileExt = file.split('.')
33 fileExt = fileExt[fileExt.length - 1]
34 return fileExt != 'js' and fileExt != 'css'
35
36 addFilesBasedOnFilter: (filterPath, namespace) ->
37 directoryPath = filterPath.substring(0, filterPath.indexOf('*'))
38
39 searchFiles = filterPath.substring(filterPath.indexOf('*.') + 1)
40 searchFiles = undefined if searchFiles == filterPath
41 searchNested = filterPath.indexOf('**') > -1
42
43
44 foundFiles = []
45 directoryFind = (dir, retrying=false) ->
46 try
47 files = fs.readdirSync(dir)
48
49 for file in files
50 file = dir + '/' + file
51 if file.indexOf('.') > -1
52 if searchFiles
53 if file.indexOf(searchFiles) > -1
54 foundFiles.push file
55 else
56 foundFiles.push file
57
58 else if searchNested
59 directoryFind(file)
60 catch err
61 if err.code == 'ENOENT'
62 unless retrying
63 # We need to retry to see if it matches a directory
64 # based on a earlier directory in the path. As an
65 # example "/path/to/dir* should match /path/to/directory/
66 closestDir = dir.split('/')
67 dir = closestDir.splice(0, closestDir.length-1).join('/')
68 searchFiles = dir + '/' + closestDir.splice(closestDir.length-1).join('')
69 searchNested = true
70 directoryFind(dir, true)
71 else
72 # Found no files when retrying either...
73 return
74 else
75 console.log err
76 directoryFind(directoryPath)
77
78 foundFiles = foundFiles.sort()
79 for file in foundFiles
80 @addFile(file, namespace)
81
82
83 addFile:(file, namespace=@defaultNamespace) =>
84 file = path.normalize(file)
85
86 for f in @files
87 # File already exists!
88 return if file == f.origFile
89
90 # Check if the file is a "filter path"
91 if file.indexOf('*') > -1
92 return @addFilesBasedOnFilter(file, namespace)
93
94 relativeFile = @_getRelativePath(file)
95 origFile = file
96 needsCompiling = false
97
98 # Determine if we need to copy/compile
99 # the file into the staticRoot folder
100 if (file.indexOf(@options.staticRoot) == -1 or @_needsCompiling(file))
101 writeTo = path.normalize(@_convertFilename(@options.staticRoot + '/generated/' + relativeFile))
102 needsCompiling = true
103 file = writeTo
104 relativeFile = @_getRelativePath(file)
105
106 url = @options.staticUrlRoot + relativeFile
107
108 url = normalizeUrl(url)
109 @files.push
110 url: url
111 file: file
112 origFile: origFile
113 needsCompiling: needsCompiling
114 namespace: namespace
115
116 toBundles: =>
117 toBundle = (namespace, files) =>
118 str = ''
119 for file in files
120 if file.namespace == namespace
121 @_compile(file.origFile, file.file)
122 str += fs.readFileSync(file.file, 'utf-8').trim('\n') + '\n'
123
124 str = @minify(str)
125 hash = crypto.createHash('md5').update(str).digest('hex')
126 filepath = "#{@options.staticRoot}/generated/bundle/#{hash.substring(0, 7)}_#{namespace}#{@fileExtension}"
127
128 writeToFile(filepath, str)
129
130 return filepath
131
132 files = @files
133 @files = []
134
135 bundles = []
136 for file in files
137 bundles.push file.namespace unless file.namespace in bundles
138
139 @addFile(toBundle(bundle, files), bundle) for bundle in bundles
140
141 _compile: (file, writeTo) =>
142 compiler.compileFile(@options.compilers, file, (err, content) ->
143 writeToFile(writeTo, content)
144 )
145 return writeTo
146
147module.exports = Bundle