You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
598 lines
16 KiB
598 lines
16 KiB
// 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;
|