// Generated by CoffeeScript 1.6.3 var Backbone, FileModel, Iconv, Model, TaskGroup, balUtil, docpadUtil, extendr, extractOptsAndCallback, 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'); extendr = require('extendr'); extractOptsAndCallback = require('extract-opts').extractOptsAndCallback; jschardet = null; Iconv = null; _ref = require('../base'), Backbone = _ref.Backbone, Model = _ref.Model; docpadUtil = require('../util'); FileModel = (function(_super) { __extends(FileModel, _super); function FileModel() { _ref1 = FileModel.__super__.constructor.apply(this, arguments); return _ref1; } FileModel.prototype.klass = FileModel; FileModel.prototype.type = 'file'; FileModel.prototype.outDirPath = null; FileModel.prototype.detectEncoding = false; FileModel.prototype.stat = null; FileModel.prototype.data = null; FileModel.prototype.buffer = null; FileModel.prototype.meta = null; FileModel.prototype.getOpts = function() { return { outDirPath: this.outDirPath, detectEncoding: this.detectEncoding, stat: this.stat, data: this.data, buffer: this.buffer, meta: this.meta }; }; FileModel.prototype.clone = function() { var attrs, instance, opts; opts = this.getOpts(); attrs = this.getAttributes(); instance = new this.klass(attrs, opts); instance._events = extendr.deepExtend(this._events); return instance; }; FileModel.prototype.defaults = { id: null, basename: null, outBasename: null, extension: null, outExtension: null, extensions: null, filename: null, fullPath: null, fullDirPath: null, outPath: null, outDirPath: null, outFilename: null, relativePath: null, relativeOutPath: null, relativeDirPath: null, relativeOutDirPath: null, relativeBase: null, releativeOutBase: 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() { var attrs; attrs = this.toJSON(); attrs = extendr.dereference(attrs); return attrs; }; FileModel.prototype.toJSON = function() { var data; data = FileModel.__super__.toJSON.apply(this, arguments); data.meta = this.getMeta().toJSON(); return data; }; 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) { var _ref2; attrs = (_ref2 = typeof attrs.toJSON === "function" ? attrs.toJSON() : void 0) != null ? _ref2 : 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.getFilename = function(_arg) { var filePath, filename, fullPath, relativePath; filename = _arg.filename, fullPath = _arg.fullPath, relativePath = _arg.relativePath; filename || (filename = this.get('filename')); if (!filename) { filePath = this.get('fullPath') || this.get('relativePath'); if (filePath) { filename = pathUtil.basename(filePath); } } return filename || null; }; FileModel.prototype.getExtensions = function(_arg) { var extensions, filename; extensions = _arg.extensions, filename = _arg.filename; extensions || (extensions = this.get('extensions') || null); if ((extensions || []).length === 0) { filename = this.getFilename({ filename: filename }); if (filename) { extensions = docpadUtil.getExtensions(filename); } } return extensions || null; }; 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 buffer, data, defaults, detectEncoding, meta, outDirPath, stat; if (opts == null) { opts = {}; } outDirPath = opts.outDirPath, detectEncoding = opts.detectEncoding, stat = opts.stat, data = opts.data, buffer = opts.buffer, 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.buffer != null) { buffer = attrs.buffer; delete attrs.buffer; delete this.attributes.buffer; } if (buffer != null) { this.setBuffer(buffer); } 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.load = function(opts, next) { var buffer, data, exists, file, filePath, fullPath, tasks, _ref2, _ref3, _this = this; if (opts == null) { opts = {}; } _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1]; file = this; exists = (_ref3 = opts.exists) != null ? _ref3 : false; fullPath = this.get('fullPath'); filePath = fullPath || this.get('relativePath') || this.get('filename'); file.log('debug', "Loading the file: " + filePath); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } file.log('debug', "Loaded the file: " + filePath); 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 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1]; 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, err, extension, extensions, filename, fullDirPath, fullPath, meta, mtime, name, outBasename, outContentType, outDirPath, outExtension, outFilename, outPath, relativeBase, relativeDirPath, relativeOutBase, relativeOutDirPath, relativeOutPath, relativePath, slug, url, _defaultUrl, _ref2; if (opts == null) { opts = {}; } _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1]; changes = {}; meta = this.getMeta(); filename = opts.filename || this.get('filename') || null; relativePath = opts.relativePath || this.get('relativePath') || null; fullPath = opts.fullPath || this.get('fullPath') || null; mtime = opts.mtime || this.get('mtime') || null; date = opts.date || meta.get('date') || null; name = opts.name || meta.get('name') || null; slug = opts.slug || meta.get('slug') || null; url = opts.url || meta.get('url') || null; contentType = opts.contentType || meta.get('contentType') || null; outContentType = opts.outContentType || meta.get('outContentType') || null; outFilename = opts.outFilename || meta.get('outFilename') || null; outExtension = opts.outExtension || meta.get('outExtension') || null; outPath = opts.outPath || meta.get('outPath') || null; extensions = null; extension = null; basename = null; outBasename = null; relativeOutPath = null; relativeDirPath = null; relativeOutDirPath = null; relativeBase = null; relativeOutBase = null; outDirPath = null; fullDirPath = null; changes.filename = filename = this.getFilename({ filename: filename, relativePath: relativePath, fullPath: fullPath }); if (!filename) { err = new Error('filename is required, it can be specified via filename, fullPath, or relativePath'); return next(err); } if (!relativePath && filename) { changes.relativePath = relativePath = filename; } changes.basename = basename = docpadUtil.getBasename(filename); changes.extensions = extensions = this.getExtensions({ filename: filename }); changes.extension = extension = docpadUtil.getExtension(extensions); if (fullPath) { changes.fullDirPath = fullDirPath = docpadUtil.getDirPath(fullPath); } changes.relativeDirPath = relativeDirPath = docpadUtil.getDirPath(relativePath); changes.relativeBase = relativeBase = relativeDirPath ? pathUtil.join(relativeDirPath, basename) : basename; if (!contentType) { changes.contentType = contentType = mime.lookup(fullPath || relativePath); } if (!date) { changes.date = date = mtime || this.get('date') || new Date(); } if (!outFilename && !outPath) { changes.outFilename = outFilename = docpadUtil.getOutFilename(basename, outExtension || extensions.join('.')); } if (!outPath) { changes.outPath = outPath = pathUtil.resolve(this.outDirPath, relativeDirPath, outFilename); } changes.outDirPath = outDirPath = docpadUtil.getDirPath(outPath); changes.outFilename = outFilename = docpadUtil.getFilename(outPath); changes.outBasename = outBasename = docpadUtil.getBasename(outFilename); changes.outExtension = outExtension = docpadUtil.getExtension(outFilename); changes.relativeOutPath = relativeOutPath = outPath.replace(this.outDirPath, '').replace(/^[\/\\]/, ''); changes.relativeOutDirPath = relativeOutDirPath = docpadUtil.getDirPath(relativeOutPath); changes.relativeOutBase = relativeOutBase = pathUtil.join(relativeOutDirPath, outBasename); if (!name) { changes.name = name = outFilename; } _defaultUrl = docpadUtil.getUrl(relativeOutPath); if (url) { this.setUrl(url); this.addUrl(_defaultUrl); } else { this.setUrl(_defaultUrl); } if (!outContentType && contentType) { changes.outContentType = outContentType = mime.lookup(outPath || relativeOutPath) || contentType; } if (!slug) { changes.slug = slug = docpadUtil.getSlug(relativeOutBase); } this.set(changes); next(); return this; }; FileModel.prototype.contextualize = function(opts, next) { var _ref2; if (opts == null) { opts = {}; } _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1]; next(); return this; }; FileModel.prototype.write = function(opts, next) { var err, file, _ref2, _ref3; _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1]; 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;