mirror of
https://github.com/atlanticbiomedical/biomedjs.git
synced 2025-07-02 00:47:26 -04:00
Added node-modules
This commit is contained in:
450
node_modules/piler/lib/piler.coffee
generated
vendored
Normal file
450
node_modules/piler/lib/piler.coffee
generated
vendored
Normal file
@ -0,0 +1,450 @@
|
||||
fs = require "fs"
|
||||
path = require "path"
|
||||
crypto = require 'crypto'
|
||||
path = require "path"
|
||||
|
||||
_ = require "underscore"
|
||||
async = require "async"
|
||||
|
||||
{jsMinify, cssMinify} = require "./minify"
|
||||
OB = require "./serialize"
|
||||
compilers = require "./compilers"
|
||||
assetUrlParse = require "./asseturlparse"
|
||||
logger = require "./logger"
|
||||
|
||||
toGlobals = (globals) ->
|
||||
code = ""
|
||||
for nsString, v of globals
|
||||
code += "__SET(#{ JSON.stringify nsString }, #{ OB.stringify v });\n"
|
||||
code
|
||||
|
||||
|
||||
extension = (filename) ->
|
||||
parts = filename.split "."
|
||||
parts[parts.length-1]
|
||||
|
||||
wrapInScriptTagInline = (code) ->
|
||||
"<script type=\"text/javascript\" >\n#{ code }\n</script>\n"
|
||||
|
||||
getCompiler = (filePath) ->
|
||||
compiler = compilers[extension filePath]
|
||||
if not compiler
|
||||
throw new Error "Could not find compiler for #{ filePath }"
|
||||
compiler.render
|
||||
|
||||
#http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/
|
||||
asCodeOb = do ->
|
||||
getId = ->
|
||||
sum = crypto.createHash('sha1')
|
||||
|
||||
|
||||
if @type is "file"
|
||||
# If code is on filesystem the url to the file should only change when
|
||||
# the path to it changes.
|
||||
sum.update @filePath
|
||||
else
|
||||
# If there is no file for code code. We need to generate id from the code
|
||||
# itself.
|
||||
sum.update OB.stringify @
|
||||
|
||||
hash = sum.digest('hex').substring 10, 0
|
||||
|
||||
if @type in ["file", "module"]
|
||||
filename = path.basename @filePath
|
||||
filename = filename.replace /\./g, "_"
|
||||
filename = filename.replace /\-/g, "_"
|
||||
hash = filename + "_" + hash
|
||||
|
||||
return hash
|
||||
pilers =
|
||||
raw: (ob, cb) -> cb null, ob.raw
|
||||
object: (ob, cb) ->
|
||||
cb null, toGlobals ob.object
|
||||
exec: (ob, cb) ->
|
||||
cb null, executableFrom ob.object
|
||||
file: (ob, cb) ->
|
||||
fs.readFile ob.filePath, (err, data) =>
|
||||
return cb? err if err
|
||||
getCompiler(ob.filePath) ob.filePath, data.toString(), (err, code) ->
|
||||
cb err, code
|
||||
|
||||
module: (ob, cb) ->
|
||||
this.file ob, (err, code) ->
|
||||
return cb? err if err
|
||||
cb null, """require.register("#{ path.basename(ob.filePath).split(".")[0] }", function(module, exports, require) {
|
||||
#{ code }
|
||||
});"""
|
||||
|
||||
|
||||
return ->
|
||||
@getId = getId
|
||||
@getCode = (cb) ->
|
||||
pilers[@type] @, cb
|
||||
return @
|
||||
|
||||
|
||||
class BasePile
|
||||
urlRoot: "/piler/"
|
||||
|
||||
production: false
|
||||
|
||||
constructor: (@name, @production, urlRoot) ->
|
||||
if urlRoot?
|
||||
@urlRoot = urlRoot
|
||||
|
||||
@code = []
|
||||
@rawPile = null
|
||||
@urls = []
|
||||
@devMapping = {}
|
||||
@piledUp = false
|
||||
|
||||
addFile: (filePath) ->
|
||||
filePath = path.normalize filePath
|
||||
@warnPiledUp "addFile"
|
||||
if filePath not in @getFilePaths()
|
||||
@code.push asCodeOb.call
|
||||
type: "file"
|
||||
filePath: filePath
|
||||
|
||||
|
||||
addRaw: (raw) ->
|
||||
@warnPiledUp "addRaw"
|
||||
@code.push asCodeOb.call
|
||||
type: "raw"
|
||||
raw: raw
|
||||
|
||||
getFilePaths: ->
|
||||
(ob.filePath for ob in @code when ob.type is "file")
|
||||
|
||||
addUrl: (url) ->
|
||||
if url not in @urls
|
||||
@urls.push url
|
||||
|
||||
|
||||
getSources: ->
|
||||
devCacheKey = Date.now()
|
||||
|
||||
# Start with plain urls
|
||||
sources = ([u] for u in @urls)
|
||||
|
||||
if @production
|
||||
sources.push ["#{ @urlRoot }min/#{ @pileHash }/#{ @name }.#{ @ext }"]
|
||||
else
|
||||
for ob in @code
|
||||
sources.push ["#{ @urlRoot }dev/#{ devCacheKey }/#{ @name }.#{ ob.type }-#{ ob.getId() }.#{ @ext }", "id=\"pile-#{ ob.getId() }\""]
|
||||
return sources
|
||||
|
||||
|
||||
findCodeObById: (id) ->
|
||||
(codeOb for codeOb in @code when codeOb.getId() is id)[0]
|
||||
|
||||
findCodeObByFilePath: (path) ->
|
||||
(codeOb for codeOb in @code when codeOb.filePath is id)[0]
|
||||
|
||||
|
||||
|
||||
_computeHash: ->
|
||||
sum = crypto.createHash('sha1')
|
||||
sum.update @rawPile
|
||||
@pileHash = sum.digest('hex')
|
||||
|
||||
warnPiledUp: (fnname) ->
|
||||
if @piledUp
|
||||
@logger.warn "Warning pile #{ @name } has been already piled up. Calling #{ fnname } does not do anything."
|
||||
|
||||
pileUp: (cb) ->
|
||||
@piledUp = true
|
||||
|
||||
async.map @code, (codeOb, cb) =>
|
||||
codeOb.getCode (err, code) =>
|
||||
return cb? err if err
|
||||
cb null, @commentLine("#{ codeOb.type }: #{ codeOb.getId() }") + "\n#{ code }"
|
||||
|
||||
, (err, result) =>
|
||||
return cb? err if err
|
||||
@rawPile = @minify result.join("\n\n").trim()
|
||||
@_computeHash()
|
||||
cb? null, @rawPile
|
||||
|
||||
|
||||
|
||||
|
||||
class JSPile extends BasePile
|
||||
ext: "js"
|
||||
|
||||
commentLine: (line) ->
|
||||
return "// #{ line.trim() }"
|
||||
|
||||
minify: (code) ->
|
||||
if @production
|
||||
jsMinify code
|
||||
else
|
||||
code
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@objects = []
|
||||
|
||||
|
||||
# CommonJS module
|
||||
addModule: (filePath) ->
|
||||
filePath = path.normalize filePath
|
||||
@warnPiledUp "addFile"
|
||||
if filePath not in @getFilePaths()
|
||||
@code.push asCodeOb.call
|
||||
type: "module"
|
||||
filePath: filePath
|
||||
|
||||
|
||||
addOb: (ob) ->
|
||||
@warnPiledUp "addOb"
|
||||
@code.push asCodeOb.call
|
||||
type: "object"
|
||||
object: ob
|
||||
|
||||
|
||||
addExec: (fn) ->
|
||||
@warnPiledUp "addExec"
|
||||
@code.push asCodeOb.call
|
||||
type: "exec"
|
||||
object: fn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class CSSPile extends BasePile
|
||||
ext: "css"
|
||||
|
||||
commentLine: (line) ->
|
||||
return "/* #{ line.trim() } */"
|
||||
|
||||
minify: (code) ->
|
||||
if @production
|
||||
cssMinify code
|
||||
else
|
||||
code
|
||||
|
||||
|
||||
defNs = (fn) ->
|
||||
(ns, path) ->
|
||||
if arguments.length is 1
|
||||
path = ns
|
||||
ns = "global"
|
||||
fn.call this, ns, path
|
||||
|
||||
|
||||
class PileManager
|
||||
|
||||
Type: null
|
||||
|
||||
constructor: (@settings) ->
|
||||
@production = @settings.production
|
||||
@settings.urlRoot ?= "/pile/"
|
||||
@logger = @settings.logger || logger
|
||||
|
||||
|
||||
|
||||
@piles =
|
||||
global: new @Type "global", @production, @settings.urlRoot
|
||||
|
||||
getPile: (ns) ->
|
||||
pile = @piles[ns]
|
||||
if not pile
|
||||
pile = @piles[ns] = new @Type ns, @production, @settings.urlRoot
|
||||
pile
|
||||
|
||||
|
||||
addFile: defNs (ns, path) ->
|
||||
pile = @getPile ns
|
||||
pile.addFile path
|
||||
|
||||
addRaw: defNs (ns, raw) ->
|
||||
pile = @getPile ns
|
||||
pile.addRaw raw
|
||||
|
||||
addUrl: defNs (ns, url) ->
|
||||
pile = @getPile ns
|
||||
pile.addUrl url
|
||||
|
||||
pileUp: ->
|
||||
logger = @logger
|
||||
logger.notice "Start assets generation for '#{ @Type::ext }'"
|
||||
for name, pile of @piles then do (pile) =>
|
||||
pile.pileUp (err, code) =>
|
||||
throw err if err
|
||||
if @settings.outputDirectory?
|
||||
|
||||
outputPath = path.join @settings.outputDirectory, "#{ pile.name }.#{ pile.ext }"
|
||||
|
||||
fs.writeFile outputPath, code, (err) ->
|
||||
throw err if err
|
||||
logger.info "Wrote #{ pile.ext } pile #{ pile.name } to #{ outputPath }"
|
||||
|
||||
getSources: (namespaces...) ->
|
||||
if typeof _.last(namespaces) is "object"
|
||||
opts = namespaces.pop()
|
||||
else
|
||||
opts = {}
|
||||
|
||||
if not opts.disableGlobal
|
||||
namespaces.unshift "global"
|
||||
|
||||
sources = []
|
||||
for ns in namespaces
|
||||
if pile = @piles[ns]
|
||||
sources.push pile.getSources()...
|
||||
return sources
|
||||
|
||||
renderTags: (namespaces...) ->
|
||||
|
||||
tags = ""
|
||||
for src in @getSources namespaces...
|
||||
tags += @wrapInTag src[0], src[1]
|
||||
tags += "\n"
|
||||
return tags
|
||||
|
||||
bind: (app, server=null) ->
|
||||
|
||||
@app = app
|
||||
@server = server
|
||||
|
||||
listener = if server then server else app
|
||||
listener.on "listening", =>
|
||||
@pileUp()
|
||||
|
||||
|
||||
@setMiddleware app
|
||||
|
||||
|
||||
app.use (req, res, next) =>
|
||||
|
||||
if not _.startsWith req.url, @settings.urlRoot
|
||||
return next()
|
||||
|
||||
res.setHeader "Content-type", @contentType
|
||||
asset = assetUrlParse req.url
|
||||
|
||||
# Wrong asset type. Lets skip to next middleware.
|
||||
if asset.ext isnt @Type::ext
|
||||
return next()
|
||||
|
||||
pile = @piles[asset.name]
|
||||
|
||||
if not pile
|
||||
res.send "Cannot find pile #{ asset.name }", 404
|
||||
return
|
||||
|
||||
# TODO: set cache headers to forever
|
||||
if asset.min
|
||||
res.end pile.rawPile
|
||||
return
|
||||
|
||||
codeOb = pile.findCodeObById asset.dev.uid
|
||||
codeOb.getCode (err, code) ->
|
||||
throw err if err
|
||||
res.end code
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
class JSManager extends PileManager
|
||||
Type: JSPile
|
||||
contentType: "application/javascript"
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@piles.global.addExec ->
|
||||
window._NS = (nsString) ->
|
||||
parent = window
|
||||
for ns in nsString.split "."
|
||||
# Create new namespace if it is missing
|
||||
parent = parent[ns] ?= {}
|
||||
parent # return the asked namespace
|
||||
|
||||
window.__SET = (ns, ob) ->
|
||||
parts = ns.split "."
|
||||
if parts.length is 1
|
||||
window[parts[0]] = ob
|
||||
else
|
||||
nsOb = _NS(parts.slice(0, -1).join("."))
|
||||
target = parts.slice(-1)[0]
|
||||
nsOb[target] = ob
|
||||
|
||||
wrapInTag: (uri, extra="") ->
|
||||
"<script type=\"text/javascript\" src=\"#{ uri }\" #{ extra } ></script>"
|
||||
|
||||
addModule: defNs (ns, path) ->
|
||||
pile = @getPile ns
|
||||
pile.addModule path
|
||||
|
||||
addOb: defNs (ns, ob) ->
|
||||
pile = @getPile ns
|
||||
pile.addOb ob
|
||||
|
||||
addExec: defNs (ns, fn) ->
|
||||
pile = @getPile ns
|
||||
pile.addExec fn
|
||||
|
||||
|
||||
setMiddleware: (app) ->
|
||||
responseExec = (fn) ->
|
||||
# "this" is the response object
|
||||
this._responseFns.push fn
|
||||
|
||||
responseOb = (ob) ->
|
||||
this._responseObs.push ob
|
||||
|
||||
# Middleware that adds add & exec methods to response objects.
|
||||
app.use (req, res, next) ->
|
||||
res._responseFns ?= []
|
||||
res._responseObs ?= []
|
||||
|
||||
# TODO: deprecate res.exec
|
||||
res.exec = res.addExec = responseExec
|
||||
res.addOb = responseOb
|
||||
|
||||
next()
|
||||
|
||||
class CSSManager extends PileManager
|
||||
Type: CSSPile
|
||||
contentType: "text/css"
|
||||
|
||||
wrapInTag: (uri, extra="") ->
|
||||
"<link rel=\"stylesheet\" href=\"#{ uri }\" #{ extra } />"
|
||||
|
||||
setMiddleware: (app) ->
|
||||
|
||||
# Creates immediately executable string presentation of given function.
|
||||
# context will be function's "this" if given.
|
||||
executableFrom = (fn, context) ->
|
||||
return "(#{ fn })();\n" unless context
|
||||
return "(#{ fn }).call(#{ context });\n"
|
||||
|
||||
|
||||
|
||||
LiveUpdateMixin = require "./livecss"
|
||||
_.extend JSManager::, LiveUpdateMixin::
|
||||
|
||||
exports.production = production = process.env.NODE_ENV is "production"
|
||||
|
||||
exports.CSSPile = CSSPile
|
||||
exports.JSPile = JSPile
|
||||
exports.JSManager = JSManager
|
||||
exports.CSSManager = CSSManager
|
||||
|
||||
exports.createJSManager = (settings={}) ->
|
||||
settings.production = production
|
||||
new JSManager settings
|
||||
|
||||
exports.createCSSManager = (settings={}) ->
|
||||
settings.production = production
|
||||
new CSSManager settings
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user