UNPKG

6.73 kBJavaScriptView Raw
1var unpack = require('browser-unpack')
2var builtins = require('builtins')
3var through = require('through')
4var flatten = require('flatten')
5var duplex = require('duplexer')
6var pluck = require('plucker')
7var uniq = require('uniq')
8
9var commondir = require('commondir')
10var fileTree = require('file-tree')
11var path = require('path')
12var fs = require('fs')
13var bl = require('bl')
14
15var versions = require('./lib/versions')
16
17module.exports = createStream
18createStream.json = json
19createStream.bundle = bundle
20
21function createStream(opts) {
22 opts = opts || {}
23
24 var buffer = bl(function(err, content) {
25 if (err) return stream.emit('error', err)
26
27 bundle(content, opts, function(err, html) {
28 if (err) return stream.emit('error', err)
29
30 output.queue(html)
31 output.queue(null)
32 })
33 })
34
35 var output = through()
36 var stream = duplex(buffer, output)
37
38 return stream
39}
40
41function json(bundles, callback) {
42 var modules = flatten(bundles
43 .map(String)
44 .map(unpack)
45 ).map(function(module) {
46 if (typeof module === 'undefined') return callback(new Error(
47 'Unable to compile one of the supplied bundles!'
48 ))
49
50 if (typeof module.id !== 'number') return module
51
52 return callback(new Error(
53 'Please recompile this browserify bundle using the --full-paths flag ' +
54 '(when using the command-line interface) or with the fullPaths option ' +
55 'set to true (when using the JavaScript API).'
56 ))
57 })
58
59 modules = modules.filter(function(module) {
60 return module && !isEmpty(module)
61 })
62
63 if (!modules.length) return
64
65 modules.forEach(function (m) {
66 if (! isAbsolute(m.id)) {
67 // modules included with browserify -r
68 if (m.id[0] == '.') {
69 // "-r ./foobar"
70 m.id = path.resolve(m.id);
71 } else {
72 // "-r foobar"
73 // assume it's under node_modules
74 m.id = path.join(path.resolve('node_modules', m.id), 'index.js');
75 }
76 }
77 });
78 var browserifyModules = modules.filter(fromBrowserify(true))
79 var otherModules = modules.filter(function(module) {
80 if (path.basename(module.id) === '_empty.js') return false
81 if (browserifyModules.indexOf(module) === -1) return true
82 })
83
84 var root = commondir(otherModules.map(pluck('id')))
85
86 browserifyModules.forEach(function(module) {
87 var regex = /^.+\/node_modules\/browserify\/(?:node_modules\/)(.+)$/g
88
89 module.id = module.id.replace(regex, function(_, subpath) {
90 return path.resolve(root, 'browserify-core/' + subpath)
91 })
92
93 return module
94 })
95
96 uniq(modules, function(a, b) {
97 return a.id === b.id ? 0 : 1
98 }, true)
99
100 var ids = modules.map(pluck('id'))
101 var main = path.basename(root)
102
103 var byid = modules.reduce(function(memo, mod) {
104 memo[mod.id] = mod
105 return memo
106 }, {})
107
108 fileTree(ids, function(id, next) {
109 var row = byid[id]
110 if (! row) {
111 return next(new Error('Unknown module ' + id + ', did you compile with --full-paths?'));
112 }
113
114 next(null, {
115 size: row.source.length
116 , deps: Object.keys(row.deps).length
117 , path: id
118 })
119 }, function(err, tree) {
120 if (err) return callback(err)
121
122 tree = { name: main, children: tree }
123 dirsizes(tree)
124 versions(tree)
125 callback(null, tree)
126 })
127}
128
129function bundle(bundles, opts, callback) {
130 bundles = Array.isArray(bundles)
131 ? bundles
132 : bundles ? [bundles] : []
133
134 if (typeof opts === 'function') {
135 callback = opts
136 opts = {}
137 }
138
139 opts = opts || {}
140 callback = callback || noop
141
142 var header = opts.header || opts.button || ''
143 var footer = opts.footer || ''
144
145 return json(bundles, function(err, data) {
146 if (err) return callback(err)
147
148 data.mode = opts.mode || 'size'
149 data = '<script type="text/javascript">'
150 + ';window.disc = ('
151 + JSON.stringify(data)
152 + ');</script>'
153
154 var script = '<script type="text/javascript">'
155 + bundled().replace(/\/script/gi, '\\/script')
156 + '</script>'
157
158 callback(null, template()({
159 scripts: script
160 , styles: styles()
161 , markdown: footer
162 , header: header
163 , data: data
164 }))
165 })
166}
167
168function template() {
169 if (template.text) return template.text
170 return template.text = require('./lib/lazy-template')(
171 fs.readFileSync(__dirname + '/src/base.html', 'utf8')
172 )
173}
174
175function styles() {
176 if (styles.text) return styles.text
177 return styles.text = fs.readFileSync(__dirname + '/build/style.css', 'utf8')
178}
179
180function bundled() {
181 if (bundled.text) return bundled.text
182 return bundled.text = fs.readFileSync(__dirname + '/build/bundle.js', 'utf8')
183}
184
185function dirsizes(child) {
186 return child.size = "size" in child ? child.size : child.children.reduce(function(size, child) {
187 return size + ("size" in child ? child.size : dirsizes(child))
188 }, 0)
189}
190
191function noop(){}
192
193function fromBrowserify(yes) {
194 var existsCache = {}
195 var no = !yes
196
197 return function(module) {
198 var search = '/node_modules/browserify'
199 var idx = module.id.indexOf(search)
200 var from = idx !== -1
201
202 if (!from) return no
203
204 // special case for process.js
205 // from insert-module-globals
206 if (
207 module.id.indexOf('insert-module-globals') !== -1 &&
208 module.id.split(path.sep).slice(-2).join('/') === 'process/browser.js'
209 ) return yes
210
211 // Look up browserify's builtins file to
212 // determine if this file is part of browserify
213 // core.
214 var builtinFile = (
215 module.id.slice(0, idx + search.length) +
216 '/lib/builtins.js'
217 )
218
219 if (!(builtinFile in existsCache)) {
220 existsCache[builtinFile] = values(
221 fs.existsSync(builtinFile) &&
222 require(builtinFile) || {}
223 )
224 }
225
226 var localBuiltins = existsCache[builtinFile]
227 var bidx = localBuiltins.indexOf(module.id)
228
229 if (bidx !== -1) return yes
230
231 // Guess remaining helper files based on module
232 // name: this should probably be improved in the
233 // future.
234 var split = module.id.split(path.sep)
235 var j = split.length - 1
236
237 while (split[--j] !== 'node_modules');;
238
239 var dir = split.slice(j + 1)[0].replace(/\-(?:browser(?:ify)?|es3)$/g, '')
240 if (dir === 'Base64') return yes
241 if (dir === 'base64-js') return yes
242 if (dir === 'inherits') return yes
243 if (dir === 'process') return yes
244 if (dir === 'ieee754') return yes
245 if (builtins.indexOf(dir) !== -1) return yes
246
247 return no
248 }
249}
250
251function values(object) {
252 return Object.keys(object).map(function(key) {
253 return object[key]
254 })
255}
256
257function isEmpty(module) {
258 return (
259 path.basename(module.id) === '_empty.js' &&
260 (!fs.existsSync(module.id) || !fs.statSync(module.id).size)
261 )
262}
263
264function isAbsolute(file) {
265 return file.match(/^([A-Za-z]:)?\/|\\/);
266}