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:
29
node_modules/piler/lib/asseturlparse.coffee
generated
vendored
Normal file
29
node_modules/piler/lib/asseturlparse.coffee
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
_ = require 'underscore'
|
||||
_.mixin require 'underscore.string'
|
||||
|
||||
module.exports = p = (url) ->
|
||||
ob = {}
|
||||
|
||||
# remove qs
|
||||
url = _.first url.split "?"
|
||||
[__..., mode, cachekey, filename] = url.split "/"
|
||||
|
||||
|
||||
if mode is "dev"
|
||||
[__..., name, devopt, ext] = filename.split "."
|
||||
[type, uid] = devopt.split "-"
|
||||
ob.dev =
|
||||
uid: uid
|
||||
type: type
|
||||
else
|
||||
[__..., name, ext] = filename.split "."
|
||||
ob.min = true
|
||||
|
||||
ob.name = name
|
||||
ob.ext = ext
|
||||
|
||||
return ob
|
||||
|
||||
|
||||
if require.main is module
|
||||
console.info p "/pile/dev/my.exec-123.js"
|
57
node_modules/piler/lib/compilers.coffee
generated
vendored
Normal file
57
node_modules/piler/lib/compilers.coffee
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
coffeescript = require "coffee-script"
|
||||
path = require "path"
|
||||
|
||||
try
|
||||
stylus = require "stylus"
|
||||
catch e
|
||||
|
||||
try
|
||||
nib = require "nib"
|
||||
catch e
|
||||
|
||||
try
|
||||
less = require "less"
|
||||
catch e
|
||||
|
||||
compilers =
|
||||
# Dummy compilers
|
||||
css:
|
||||
render: (filename, code, cb) -> cb null, code
|
||||
js:
|
||||
render: (filename, code, cb) -> cb null, code
|
||||
|
||||
# We always have coffee-script compiler ;)
|
||||
coffee:
|
||||
render: (filename, code, cb) ->
|
||||
try
|
||||
cb null, coffeescript.compile code
|
||||
catch e
|
||||
cb e, null
|
||||
targetExt: "js"
|
||||
|
||||
if stylus?
|
||||
compilers.styl =
|
||||
targetExt: "css"
|
||||
render: (filename, code, cb) ->
|
||||
stylus(code)
|
||||
.set('filename', filename)
|
||||
.render cb
|
||||
|
||||
if nib?
|
||||
Renderer = require "stylus/lib/renderer"
|
||||
compilers.styl.render = (filename, code, cb) ->
|
||||
stylus(code)
|
||||
.set('filename', filename)
|
||||
.use(do nib)
|
||||
.render cb
|
||||
|
||||
|
||||
if less?
|
||||
compilers.less =
|
||||
render: (filename, code, cb) ->
|
||||
less.render code,
|
||||
paths: [path.dirname filename]
|
||||
cb
|
||||
targetExt: "css"
|
||||
|
||||
module.exports = compilers
|
99
node_modules/piler/lib/livecss.coffee
generated
vendored
Normal file
99
node_modules/piler/lib/livecss.coffee
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
fs = require "fs"
|
||||
|
||||
|
||||
|
||||
try
|
||||
socketio = require('socket.io')
|
||||
catch e
|
||||
socketio = null
|
||||
|
||||
incUrlSeq = (url) ->
|
||||
seqRegexp = /(--([0-9]+))\..*$/
|
||||
match = url.match seqRegexp
|
||||
seq = parseInt match?[2] or 0, 10
|
||||
|
||||
if match
|
||||
cleanUrl = url.replace match[1], ""
|
||||
else
|
||||
cleanUrl = url
|
||||
|
||||
cleanUrl = cleanUrl.substr(0,cleanUrl.lastIndexOf('.'))+"--#{ seq+1 }"+cleanUrl.substr(cleanUrl.lastIndexOf('.'))
|
||||
|
||||
# Yep, this function will be executed in the browser.
|
||||
clientUpdater = ->
|
||||
console.log "CSS updater is active. Waiting for connection..."
|
||||
|
||||
pile = io.connect('/pile')
|
||||
|
||||
pile.on "connect", ->
|
||||
console.log "CSS updater has connected"
|
||||
|
||||
pile.on "disconnect", ->
|
||||
console.log "CSS updater has disconnected! Refresh to reconnect"
|
||||
|
||||
pile.on "update", (fileId) ->
|
||||
elem = document.getElementById "pile-" + fileId
|
||||
if elem
|
||||
console.log "updating", fileId, elem
|
||||
elem.href = PILE.incUrlSeq elem.href
|
||||
else
|
||||
console.log "id", fileId, "not found"
|
||||
|
||||
class LiveUpdateMixin
|
||||
|
||||
installSocketIo: (userio) ->
|
||||
|
||||
@addUrl "/socket.io/socket.io.js"
|
||||
@addOb PILE:
|
||||
incUrlSeq: incUrlSeq
|
||||
@addExec clientUpdater
|
||||
|
||||
if not userio
|
||||
io = socketio.listen @app
|
||||
else
|
||||
io = userio
|
||||
|
||||
# Why does not work?
|
||||
io.configure ->
|
||||
io.set 'log level', 0
|
||||
|
||||
@io = io.of "/pile"
|
||||
|
||||
|
||||
liveUpdate: (cssmanager, userio) ->
|
||||
if @production
|
||||
@logger.info "Not activating live update in production"
|
||||
return
|
||||
|
||||
if not @app
|
||||
throw new Error 'JSManager must be bind to a http server (Express app)
|
||||
before it can live update CSS'
|
||||
|
||||
@installSocketIo userio
|
||||
|
||||
listener = if @server then @server else @app
|
||||
listener.on "listening", =>
|
||||
@logger.info "Activating CSS updater"
|
||||
|
||||
for k, pile of cssmanager.piles
|
||||
for codeOb in pile.code
|
||||
@_watch pile, codeOb
|
||||
|
||||
|
||||
_watch: (pile, codeOb) ->
|
||||
return unless codeOb.type is "file"
|
||||
@logger.info "watching #{ codeOb.filePath } for changes"
|
||||
fs.watch codeOb.filePath, =>
|
||||
@logger.info "updated", codeOb.filePath
|
||||
@io.emit "update", codeOb.getId()
|
||||
|
||||
# For testing
|
||||
LiveUpdateMixin.incUrlSeq = incUrlSeq
|
||||
|
||||
if socketio?
|
||||
module.exports = LiveUpdateMixin
|
||||
else
|
||||
module.exports = class LiveUpdateDisabled
|
||||
liveUpdate: ->
|
||||
@logger.error "No socket.io installed. Live update won't work."
|
||||
|
8
node_modules/piler/lib/logger.coffee
generated
vendored
Normal file
8
node_modules/piler/lib/logger.coffee
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Basic Logger functionality
|
||||
exports.debug = console.debug
|
||||
exports.notice = console.log
|
||||
exports.info = console.info
|
||||
exports.warn = console.warn
|
||||
exports.warning = console.warn
|
||||
exports.error = console.error
|
||||
exports.critical = console.error
|
35
node_modules/piler/lib/minify.coffee
generated
vendored
Normal file
35
node_modules/piler/lib/minify.coffee
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Simple wrappers for JS and CSS minifiers so that they are easy to change if
|
||||
# needed.
|
||||
#
|
||||
|
||||
csso = require "csso"
|
||||
|
||||
try
|
||||
uglify = require("uglify-js")
|
||||
catch error
|
||||
# uglify-js' packaging currently sucks. Add fallback.
|
||||
console.log "no uglify", error
|
||||
exports.jsMinify = (code) -> code
|
||||
exports.jsBeautify = (code) -> code
|
||||
|
||||
|
||||
exports.cssMinify = (code) -> csso.justDoIt code
|
||||
|
||||
|
||||
|
||||
if uglify?
|
||||
jsp = uglify.parser
|
||||
pro = uglify.uglify
|
||||
|
||||
exports.jsMinify = (code) ->
|
||||
ast = jsp.parse code
|
||||
ast = pro.ast_mangle ast
|
||||
ast = pro.ast_squeeze ast
|
||||
pro.gen_code ast
|
||||
|
||||
exports.jsBeautify = (code) ->
|
||||
ast = jsp.parse(code)
|
||||
pro.gen_code ast, beautify: true
|
||||
|
||||
|
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
40
node_modules/piler/lib/serialize.coffee
generated
vendored
Normal file
40
node_modules/piler/lib/serialize.coffee
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
# Remove last comma from string
|
||||
removeTrailingComma = (s) ->
|
||||
s.trim().replace(/,$/, "")
|
||||
|
||||
# Map of functions that can convert various Javascript objects to strings.
|
||||
types =
|
||||
|
||||
function: (fn) -> "#{ fn }"
|
||||
string: (s) -> JSON.stringify s # Knows how to correctly serialize strings to String literals
|
||||
number: (n) -> n.toString()
|
||||
boolean: (n) -> n.toString()
|
||||
|
||||
object: (obj) ->
|
||||
|
||||
# typeof reports array as object
|
||||
return this._array obj if Array.isArray obj
|
||||
|
||||
code = "{"
|
||||
code += "\"#{ k }\": #{ codeFrom v }," for k, v of obj
|
||||
removeTrailingComma(code) + "}"
|
||||
|
||||
_array: (array) ->
|
||||
code = "["
|
||||
code += " #{ codeFrom v }," for v in array
|
||||
removeTrailingComma(code) + "]"
|
||||
|
||||
|
||||
# Generates code string from given object. Works for numbers, strings, regexes
|
||||
# and even functions. Does not handle circular references.
|
||||
exports.stringify = codeFrom = (obj) ->
|
||||
types[typeof obj]?(obj)
|
||||
|
||||
|
||||
if require.main is module
|
||||
console.log exports.stringify
|
||||
foo: 1
|
||||
bar:
|
||||
lol: ":D"
|
||||
hah: 2
|
Reference in New Issue
Block a user