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.
 
 
 

657 lines
19 KiB

// 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;