// Generated by CoffeeScript 1.6.2 var Backbone, FileModel, Iconv, Model, TaskGroup, balUtil, jschardet, mime, pathUtil, safefs, typeChecker, _ref, _ref1, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; pathUtil = require('path'); balUtil = require('bal-util'); typeChecker = require('typechecker'); TaskGroup = require('taskgroup').TaskGroup; safefs = require('safefs'); mime = require('mime'); jschardet = null; Iconv = null; _ref = require(__dirname + '/../base'), Backbone = _ref.Backbone, Model = _ref.Model; FileModel = (function(_super) { __extends(FileModel, _super); function FileModel() { _ref1 = FileModel.__super__.constructor.apply(this, arguments); return _ref1; } FileModel.prototype.outDirPath = null; FileModel.prototype.type = 'file'; FileModel.prototype.stat = null; FileModel.prototype.data = null; FileModel.prototype.buffer = null; FileModel.prototype.meta = null; FileModel.prototype.defaults = { id: null, basename: null, extension: null, outExtension: null, extensions: null, filename: null, path: null, outPath: null, dirPath: null, outDirPath: null, outFilename: null, relativePath: null, relativeOutPath: null, relativeDirPath: null, relativeOutDirPath: null, relativeBase: null, contentType: null, outContentType: null, ctime: null, mtime: null, exists: null, encoding: null, source: null, content: null, title: null, name: null, date: null, slug: null, url: null, urls: null, ignored: false, standalone: false }; FileModel.prototype.setData = function(data) { this.data = data; return this; }; FileModel.prototype.getData = function() { return this.data; }; FileModel.prototype.setBuffer = function(buffer) { this.buffer = buffer; return this; }; FileModel.prototype.getBuffer = function() { return this.buffer; }; FileModel.prototype.setStat = function(stat) { this.stat = stat; this.set({ ctime: new Date(stat.ctime), mtime: new Date(stat.mtime) }); return this; }; FileModel.prototype.getStat = function() { return this.stat; }; FileModel.prototype.getAttributes = function() { return this.toJSON(); }; FileModel.prototype.getMeta = function() { var args, _ref2; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (this.meta === null) { this.meta = new Model(); } if (args.length) { return (_ref2 = this.meta).get.apply(_ref2, args); } else { return this.meta; } }; FileModel.prototype.setMeta = function(attrs) { this.getMeta().set(attrs); this.set(attrs); return this; }; FileModel.prototype.setMetaDefaults = function(defaults) { this.getMeta().setDefaults(defaults); this.setDefaults(defaults); return this; }; FileModel.prototype.getContent = function() { return this.get('content') || this.getBuffer(); }; FileModel.prototype.getOutContent = function() { return this.getContent(); }; FileModel.prototype.isText = function() { return this.get('encoding') !== 'binary'; }; FileModel.prototype.isBinary = function() { return this.get('encoding') === 'binary'; }; FileModel.prototype.setUrl = function(url) { this.addUrl(url); this.set({ url: url }); return this; }; FileModel.prototype.addUrl = function(url) { var existingUrl, found, newUrl, urls, _i, _j, _len, _len1; if (url instanceof Array) { for (_i = 0, _len = url.length; _i < _len; _i++) { newUrl = url[_i]; this.addUrl(newUrl); } } else if (url) { found = false; urls = this.get('urls'); for (_j = 0, _len1 = urls.length; _j < _len1; _j++) { existingUrl = urls[_j]; if (existingUrl === url) { found = true; break; } } if (!found) { urls.push(url); } this.trigger('change:urls', this, urls, {}); this.trigger('change', this, {}); } return this; }; FileModel.prototype.removeUrl = function(userUrl) { var index, url, urls, _i, _len; urls = this.get('urls'); for (index = _i = 0, _len = urls.length; _i < _len; index = ++_i) { url = urls[index]; if (url === userUrl) { urls.splice(index, 1); break; } } return this; }; FileModel.prototype.getPath = function(relativePath, parentPath) { var path, relativeDirPath; if (/^\./.test(relativePath)) { relativeDirPath = this.get('relativeDirPath'); path = pathUtil.join(relativeDirPath, relativePath); } else { if (parentPath) { path = pathUtil.join(parentPath, relativePath); } else { path = relativePath; } } return path; }; FileModel.prototype.initialize = function(attrs, opts) { var data, defaults, detectEncoding, meta, outDirPath, stat; detectEncoding = opts.detectEncoding, outDirPath = opts.outDirPath, stat = opts.stat, data = opts.data, meta = opts.meta; if (detectEncoding != null) { this.detectEncoding = detectEncoding; } if (outDirPath) { this.outDirPath = outDirPath; } defaults = { extensions: [], urls: [], id: this.cid }; if (stat) { this.setStat(stat); } else { defaults.ctime = new Date(); defaults.mtime = new Date(); } this.set(defaults); if (attrs.data != null) { data = attrs.data; delete attrs.data; delete this.attributes.data; } if (data != null) { this.setData(data); } if (attrs.meta != null) { this.setMeta(attrs.meta); delete attrs.meta; } if (meta) { this.setMeta(meta); } return FileModel.__super__.initialize.apply(this, arguments); }; FileModel.prototype.getActionArgs = function(opts, next) { if (typeChecker.isFunction(opts) && (next != null) === false) { next = opts; opts = {}; } else { opts || (opts = {}); } next || (next = opts.next || null); return { next: next, opts: opts }; }; FileModel.prototype.load = function(opts, next) { var buffer, data, exists, file, filePath, fullPath, tasks, _ref2, _ref3, _this = this; if (opts == null) { opts = {}; } _ref2 = this.getActionArgs(opts, next), opts = _ref2.opts, next = _ref2.next; file = this; exists = (_ref3 = opts.exists) != null ? _ref3 : false; fullPath = this.get('fullPath'); if (!fullPath) { filePath = this.get('relativePath') || this.get('fullPath') || this.get('filename'); fullPath = this.get('fullPath') || filePath || null; file.set({ fullPath: fullPath }); } file.log('debug', "Loading the file: " + fullPath); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } file.log('debug', "Loaded the file: " + fullPath); return file.parse(function(err) { if (err) { return next(err); } return file.normalize(function(err) { if (err) { return next(err); } return next(null, file.buffer); }); }); }); data = file.getData(); if (data != null) { buffer = new Buffer(data); file.setBuffer(buffer); } if (opts.stat) { file.setStat(opts.stat); } if (opts.buffer) { file.setBuffer(opts.buffer); } tasks.addTask(function(complete) { if (fullPath && exists && (opts.stat != null) === false) { return safefs.stat(fullPath, function(err, fileStat) { if (err) { return complete(err); } file.setStat(fileStat); return complete(); }); } else { return complete(); } }); tasks.addTask(function(complete) { if (fullPath && exists && (opts.buffer != null) === false) { return safefs.readFile(fullPath, function(err, buffer) { if (err) { return complete(err); } file.setBuffer(buffer); return complete(); }); } else { return complete(); } }); if (fullPath) { safefs.exists(fullPath, function(_exists) { exists = _exists; file.set({ exists: exists }); return tasks.run(); }); } else { tasks.run(); } return this; }; FileModel.prototype.parse = function(opts, next) { var buffer, changes, content, encoding, err, fullPath, isText, source, _ref2, _ref3, _ref4; if (opts == null) { opts = {}; } _ref2 = this.getActionArgs(opts, next), opts = _ref2.opts, next = _ref2.next; buffer = this.getBuffer(); fullPath = this.get('fullPath'); encoding = this.get('encoding') || null; changes = {}; if ((encoding != null) === false || opts.reencode === true) { isText = balUtil.isTextSync(fullPath, buffer); if (isText === true) { if (this.detectEncoding) { if (jschardet == null) { jschardet = require('jschardet'); } try { if (Iconv == null) { Iconv = require('iconv').Iconv; } } catch (_error) { err = _error; Iconv = null; } if (encoding == null) { encoding = ((_ref3 = jschardet.detect(buffer)) != null ? _ref3.encoding : void 0) || 'utf8'; } } else { if (encoding == null) { encoding = 'utf8'; } } if ((_ref4 = encoding.toLowerCase()) !== 'ascii' && _ref4 !== 'utf8' && _ref4 !== 'utf-8') { if (Iconv != null) { this.log('info', "Converting encoding " + encoding + " to UTF-8 on " + fullPath); try { buffer = new Iconv(encoding, 'utf8').convert(buffer); } catch (_error) { err = _error; this.log('warn', "Encoding conversion failed, therefore we cannot convert the encoding " + encoding + " to UTF-8 on " + fullPath); } } else { this.log('warn', "Iconv did not load, therefore we cannot convert the encoding " + encoding + " to UTF-8 on " + fullPath); } } changes.encoding = encoding; } else { encoding = 'binary'; changes.encoding = encoding; } } if (encoding === 'binary') { content = source = ''; changes.content = content; changes.source = source; } else { source = buffer.toString('utf8'); content = source; changes.content = content; changes.source = source; } this.set(changes); next(); return this; }; FileModel.prototype.normalize = function(opts, next) { var basename, changes, contentType, date, extension, extensions, filename, fullDirPath, fullPath, mtime, relativeBase, relativeDirPath, relativePath, _ref2; if (opts == null) { opts = {}; } _ref2 = this.getActionArgs(opts, next), opts = _ref2.opts, next = _ref2.next; changes = {}; basename = this.get('basename'); filename = this.get('filename'); fullPath = this.get('fullPath'); extensions = this.get('extensions'); relativePath = this.get('relativePath'); mtime = this.get('mtime'); date = this.getMeta('date') || null; if (fullPath) { changes.filename = filename = pathUtil.basename(fullPath); changes.outFilename = filename; } if (filename) { if (filename[0] === '.') { basename = filename.replace(/^(\.[^\.]+)\..*$/, '$1'); } else { basename = filename.replace(/\..*$/, ''); } changes.basename = basename; if ((extensions != null) === false || extensions.length === 0) { extensions = filename.split(/\./g); extensions.shift(); } changes.extensions = extensions; if (extensions.length) { extension = extensions[extensions.length - 1]; } else { extension = null; } changes.extension = extension; changes.outExtension = extension; } if (fullPath) { changes.fullDirPath = fullDirPath = pathUtil.dirname(fullPath) || ''; changes.contentType = contentType = mime.lookup(fullPath); changes.outContentType = contentType; } if (relativePath) { changes.relativeDirPath = relativeDirPath = pathUtil.dirname(relativePath).replace(/^\.$/, '') || ''; changes.relativeBase = relativeBase = relativeDirPath ? pathUtil.join(relativeDirPath, basename) : basename; } if (!date && mtime) { changes.date = date = mtime; } this.set(changes); next(); return this; }; FileModel.prototype.contextualize = function(opts, next) { var changes, filename, meta, name, outDirPath, outPath, relativeBase, relativeDirPath, relativeOutDirPath, relativeOutPath, relativePath, slug, url, _ref2; if (opts == null) { opts = {}; } _ref2 = this.getActionArgs(opts, next), opts = _ref2.opts, next = _ref2.next; changes = {}; meta = this.getMeta(); relativePath = this.get('relativePath'); relativeDirPath = this.get('relativeDirPath'); relativeBase = this.get('relativeBase'); filename = this.get('filename'); outPath = this.get('outPath'); outDirPath = this.get('outDirPath'); name = meta.get('name') || null; slug = meta.get('slug') || null; url = meta.get('url') || null; if (!url && relativePath) { url = "/" + relativePath; this.setUrl(url); } if (!slug && relativeBase) { changes.slug = slug = balUtil.generateSlugSync(relativeBase); } if (!name && filename) { changes.name = name = filename; } if (this.outDirPath && relativePath) { if (relativeDirPath != null) { changes.relativeOutDirPath = relativeOutDirPath = relativeDirPath; } changes.relativeOutPath = relativeOutPath = relativePath; changes.outPath = outPath = pathUtil.join(this.outDirPath, relativePath); if (outPath) { changes.outDirPath = outDirPath = pathUtil.dirname(outPath); } } this.set(changes); next(); return this; }; FileModel.prototype.write = function(opts, next) { var err, file, _ref2, _ref3; _ref2 = this.getActionArgs(opts, next), opts = _ref2.opts, next = _ref2.next; file = this; opts.path || (opts.path = this.get('outPath')); opts.encoding || (opts.encoding = this.get('encoding')); opts.content || (opts.content = this.getContent()); opts.type || (opts.type = 'file'); if (!opts.path) { next(); return this; } if ((_ref3 = opts.encoding.toLowerCase()) !== 'ascii' && _ref3 !== 'utf8' && _ref3 !== 'utf-8' && _ref3 !== 'binary') { if (Iconv != null) { this.log('info', "Converting encoding UTF-8 to " + opts.encoding + " on " + opts.path); try { opts.content = new Iconv('utf8', opts.encoding).convert(opts.content); } catch (_error) { err = _error; this.log('warn', "Encoding conversion failed, therefore we cannot convert the encoding UTF-8 to " + opts.encoding + " on " + opts.path); } } else { this.log('warn', "Iconv did not load, therefore we cannot convert the encoding UTF-8 to " + opts.encoding + " on " + opts.path); } } file.log('debug', "Writing the " + opts.type + ": " + opts.path + " " + opts.encoding); safefs.writeFile(opts.path, opts.content, function(err) { if (err) { return next(err); } file.log('debug', "Wrote the " + opts.type + ": " + opts.path + " " + opts.encoding); return next(); }); return this; }; FileModel.prototype["delete"] = function(next) { var file, fileOutPath; file = this; fileOutPath = this.get('outPath'); if (!fileOutPath) { next(); return this; } file.log('debug', "Delete the file: " + fileOutPath); safefs.exists(fileOutPath, function(exists) { if (!exists) { return next(); } return safefs.unlink(fileOutPath, function(err) { if (err) { return next(err); } file.log('debug', "Deleted the file: " + fileOutPath); return next(); }); }); return this; }; return FileModel; })(Model); module.exports = FileModel;