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.
572 lines
17 KiB
572 lines
17 KiB
// Generated by CoffeeScript 1.6.2
|
|
var CSON, DocumentModel, FileModel, TaskGroup, YAML, eachr, extendr, mime, pathUtil, _ref,
|
|
__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; },
|
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
|
|
|
pathUtil = require('path');
|
|
|
|
extendr = require('extendr');
|
|
|
|
eachr = require('eachr');
|
|
|
|
TaskGroup = require('taskgroup').TaskGroup;
|
|
|
|
mime = require('mime');
|
|
|
|
CSON = null;
|
|
|
|
YAML = null;
|
|
|
|
FileModel = require(__dirname + '/file');
|
|
|
|
DocumentModel = (function(_super) {
|
|
__extends(DocumentModel, _super);
|
|
|
|
function DocumentModel() {
|
|
_ref = DocumentModel.__super__.constructor.apply(this, arguments);
|
|
return _ref;
|
|
}
|
|
|
|
DocumentModel.prototype.type = 'document';
|
|
|
|
DocumentModel.prototype.defaults = {
|
|
referencesOthers: false,
|
|
header: null,
|
|
parser: null,
|
|
body: null,
|
|
rendered: false,
|
|
contentRendered: null,
|
|
contentRenderedWithoutLayouts: null,
|
|
dynamic: false,
|
|
tags: null,
|
|
renderSingleExtensions: false
|
|
};
|
|
|
|
DocumentModel.prototype.getOutContent = function() {
|
|
var content;
|
|
|
|
content = this.get('contentRendered') || this.get('content') || this.getBuffer();
|
|
return content;
|
|
};
|
|
|
|
DocumentModel.prototype.toJSON = function() {
|
|
var data;
|
|
|
|
data = DocumentModel.__super__.toJSON.apply(this, arguments);
|
|
data.meta = this.getMeta().toJSON();
|
|
return data;
|
|
};
|
|
|
|
DocumentModel.prototype.referencesOthers = function(flag) {
|
|
if (flag == null) {
|
|
flag = true;
|
|
}
|
|
this.set({
|
|
referencesOthers: flag
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.parse = function(opts, next) {
|
|
var buffer, key, meta, reset, value, _ref1, _ref2,
|
|
_this = this;
|
|
|
|
if (opts == null) {
|
|
opts = {};
|
|
}
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
buffer = this.getBuffer();
|
|
meta = this.getMeta();
|
|
reset = {};
|
|
_ref2 = meta.attributes;
|
|
for (key in _ref2) {
|
|
if (!__hasProp.call(_ref2, key)) continue;
|
|
value = _ref2[key];
|
|
reset[key] = this.defaults[key];
|
|
}
|
|
reset = extendr.dereference(reset);
|
|
this.set(reset);
|
|
meta.clear();
|
|
DocumentModel.__super__.parse.call(this, opts, function() {
|
|
var body, content, err, header, ignored, match, metaData, metaDate, metaUrl, metaUrls, parser, regex, seperator;
|
|
|
|
content = _this.get('content').replace(/\r\n?/gm, '\n');
|
|
regex = /^\s*(([^\s\d\w])\2{2,})(?:\x20*([a-z]+))?([\s\S]*?)\1/;
|
|
match = regex.exec(content);
|
|
metaData = {};
|
|
if (match) {
|
|
seperator = match[1];
|
|
parser = match[3] || 'yaml';
|
|
header = match[4].trim();
|
|
body = content.substring(match[0].length).trim();
|
|
try {
|
|
switch (parser) {
|
|
case 'cson':
|
|
case 'coffee':
|
|
case 'coffeescript':
|
|
case 'coffee-script':
|
|
if (!CSON) {
|
|
CSON = require('cson');
|
|
}
|
|
metaData = CSON.parseSync(header);
|
|
meta.set(metaData);
|
|
break;
|
|
case 'yaml':
|
|
if (!YAML) {
|
|
YAML = require('yamljs');
|
|
}
|
|
metaData = YAML.parse(header.replace(/\t/g, ' '));
|
|
meta.set(metaData);
|
|
break;
|
|
default:
|
|
err = new Error("Unknown meta parser: " + parser);
|
|
return next(err);
|
|
}
|
|
} catch (_error) {
|
|
err = _error;
|
|
return next(err);
|
|
}
|
|
} else {
|
|
body = content;
|
|
}
|
|
if (metaData.encoding && metaData.encoding !== _this.get('encoding')) {
|
|
_this.setMeta({
|
|
encoding: metaData.encoding
|
|
});
|
|
opts.reencode = true;
|
|
return _this.parse(opts, next);
|
|
}
|
|
body = body.replace(/^\n+/, '');
|
|
_this.set({
|
|
source: content,
|
|
content: body,
|
|
header: header,
|
|
body: body,
|
|
parser: parser,
|
|
name: _this.get('name') || _this.get('title') || _this.get('basename')
|
|
});
|
|
metaDate = meta.get('date');
|
|
if (metaDate) {
|
|
metaDate = new Date(metaDate);
|
|
meta.set({
|
|
date: metaDate
|
|
});
|
|
}
|
|
ignored = meta.get('ignored') || meta.get('ignore') || meta.get('skip') || meta.get('draft') || (meta.get('published') === false);
|
|
if (ignored) {
|
|
meta.set({
|
|
ignored: true
|
|
});
|
|
}
|
|
metaUrls = meta.get('urls');
|
|
metaUrl = meta.get('url');
|
|
if (metaUrls) {
|
|
_this.addUrl(metaUrls);
|
|
}
|
|
if (metaUrl) {
|
|
_this.addUrl(metaUrl);
|
|
}
|
|
_this.set(meta.toJSON());
|
|
return next();
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.normalize = function(opts, next) {
|
|
var _ref1,
|
|
_this = this;
|
|
|
|
if (opts == null) {
|
|
opts = {};
|
|
}
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
DocumentModel.__super__.normalize.call(this, opts, function() {
|
|
var extensions, outExtension;
|
|
|
|
extensions = _this.get('extensions');
|
|
if ((extensions != null) && extensions.length) {
|
|
outExtension = extensions[0];
|
|
_this.set({
|
|
outExtension: outExtension
|
|
});
|
|
}
|
|
return next();
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.contextualize = function(opts, next) {
|
|
var _ref1,
|
|
_this = this;
|
|
|
|
if (opts == null) {
|
|
opts = {};
|
|
}
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
DocumentModel.__super__.contextualize.call(this, opts, function() {
|
|
return _this.getEve(function(err, eve) {
|
|
var basename, changes, extensions, fullPath, meta, name, outContentType, outExtension, outFilename, outPath, relativeDirPath, relativeOutPath, url;
|
|
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
changes = {};
|
|
meta = _this.getMeta();
|
|
fullPath = _this.get('fullPath');
|
|
basename = _this.get('basename');
|
|
relativeDirPath = _this.get('relativeDirPath');
|
|
extensions = _this.get('extensions');
|
|
outExtension = _this.get('outExtension');
|
|
url = meta.get('url') || null;
|
|
name = meta.get('name') || null;
|
|
outPath = meta.get('outPath') || null;
|
|
outFilename = null;
|
|
if (eve != null) {
|
|
outExtension = eve.get('outExtension');
|
|
}
|
|
if (basename && outExtension) {
|
|
if (basename[0] === '.' && outExtension === extensions[0]) {
|
|
outFilename = basename;
|
|
} else {
|
|
outFilename = "" + basename + "." + outExtension;
|
|
}
|
|
changes.outFilename = outFilename;
|
|
}
|
|
if (outFilename) {
|
|
if (relativeDirPath) {
|
|
relativeOutPath = "" + relativeDirPath + "/" + outFilename;
|
|
} else {
|
|
relativeOutPath = "" + outFilename;
|
|
}
|
|
changes.relativeOutPath = relativeOutPath;
|
|
if (!url) {
|
|
changes.url = url = "/" + relativeOutPath;
|
|
}
|
|
}
|
|
if (!name && (outFilename != null)) {
|
|
changes.name = name = outFilename;
|
|
}
|
|
if (_this.outDirPath && relativeOutPath) {
|
|
changes.outPath = outPath = pathUtil.join(_this.outDirPath, relativeOutPath);
|
|
}
|
|
if (url) {
|
|
_this.removeUrl(_this.get('url'));
|
|
_this.setUrl(url);
|
|
}
|
|
if (outPath || fullPath) {
|
|
changes.outContentType = outContentType = mime.lookup(outPath || fullPath);
|
|
}
|
|
_this.set(changes);
|
|
return next();
|
|
});
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.hasLayout = function() {
|
|
return this.get('layout') != null;
|
|
};
|
|
|
|
DocumentModel.prototype.getLayout = function(next) {
|
|
var file, layoutSelector;
|
|
|
|
file = this;
|
|
layoutSelector = this.get('layout');
|
|
if (!layoutSelector) {
|
|
return next(null, null);
|
|
}
|
|
this.emit('getLayout', {
|
|
selector: layoutSelector
|
|
}, function(err, opts) {
|
|
var layout;
|
|
|
|
layout = opts.layout;
|
|
if (err) {
|
|
file.set({
|
|
'layoutId': null
|
|
});
|
|
return next(err);
|
|
} else if (!layout) {
|
|
file.set({
|
|
'layoutId': null
|
|
});
|
|
err = new Error("Could not find the specified layout: " + layoutSelector);
|
|
return next(err);
|
|
} else {
|
|
file.set({
|
|
'layoutId': layout.id
|
|
});
|
|
return next(null, layout);
|
|
}
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.getEve = function(next) {
|
|
if (this.hasLayout()) {
|
|
this.getLayout(function(err, layout) {
|
|
if (err) {
|
|
return next(err, null);
|
|
} else {
|
|
return layout.getEve(next);
|
|
}
|
|
});
|
|
} else {
|
|
next(null, this);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.renderExtensions = function(opts, next) {
|
|
var content, extension, extensions, extensionsReversed, file, filename, renderSingleExtensions, result, tasks, templateData, _i, _len;
|
|
|
|
file = this;
|
|
extensions = this.get('extensions');
|
|
filename = this.get('filename');
|
|
content = opts.content, templateData = opts.templateData, renderSingleExtensions = opts.renderSingleExtensions;
|
|
if (content == null) {
|
|
content = this.get('body');
|
|
}
|
|
if (templateData == null) {
|
|
templateData = {};
|
|
}
|
|
if (renderSingleExtensions == null) {
|
|
renderSingleExtensions = this.get('renderSingleExtensions');
|
|
}
|
|
result = content;
|
|
extensionsReversed = [];
|
|
if (extensions.length === 0 && filename) {
|
|
extensionsReversed.push(filename);
|
|
}
|
|
for (_i = 0, _len = extensions.length; _i < _len; _i++) {
|
|
extension = extensions[_i];
|
|
extensionsReversed.unshift(extension);
|
|
}
|
|
if (renderSingleExtensions && extensionsReversed.length === 1) {
|
|
if (renderSingleExtensions !== 'auto' || filename.replace(/^\./, '') === extensionsReversed[0]) {
|
|
extensionsReversed.push(null);
|
|
}
|
|
}
|
|
if (extensionsReversed.length <= 1) {
|
|
return next(null, result);
|
|
}
|
|
tasks = new TaskGroup().once('complete', function(err) {
|
|
return next(err, result);
|
|
});
|
|
eachr(extensionsReversed.slice(1), function(extension, index) {
|
|
return tasks.addTask(function(complete) {
|
|
var eventData;
|
|
|
|
eventData = {
|
|
inExtension: extensionsReversed[index],
|
|
outExtension: extension,
|
|
templateData: templateData,
|
|
file: file,
|
|
content: result
|
|
};
|
|
return file.trigger('render', eventData, function(err) {
|
|
var message;
|
|
|
|
if (err) {
|
|
return complete(err);
|
|
}
|
|
if (result && result === eventData.content) {
|
|
message = "\n Rendering the extension \"" + eventData.inExtension + "\" to \"" + eventData.outExtension + "\" on \"" + (file.attributes.relativePath || file.attributes.fullPath) + "\" didn't do anything.\n Explanation here: http://docpad.org/extension-not-rendering";
|
|
file.log('warn', message);
|
|
return complete();
|
|
}
|
|
result = eventData.content;
|
|
return complete();
|
|
});
|
|
});
|
|
});
|
|
tasks.run();
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.renderDocument = function(opts, next) {
|
|
var content, eventData, extension, file, templateData, _ref1;
|
|
|
|
file = this;
|
|
extension = this.get('extensions')[0];
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
content = opts.content, templateData = opts.templateData;
|
|
if (content == null) {
|
|
content = this.get('body');
|
|
}
|
|
if (templateData == null) {
|
|
templateData = {};
|
|
}
|
|
eventData = {
|
|
extension: extension,
|
|
templateData: templateData,
|
|
file: file,
|
|
content: content
|
|
};
|
|
file.trigger('renderDocument', eventData, function(err) {
|
|
return next(err, eventData.content);
|
|
});
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.renderLayouts = function(opts, next) {
|
|
var content, file, templateData, _ref1;
|
|
|
|
file = this;
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
content = opts.content, templateData = opts.templateData;
|
|
if (content == null) {
|
|
content = this.get('body');
|
|
}
|
|
if (templateData == null) {
|
|
templateData = {};
|
|
}
|
|
return file.getLayout(function(err, layout) {
|
|
if (err) {
|
|
return next(err, content);
|
|
}
|
|
if (layout) {
|
|
templateData.content = content;
|
|
return layout.render({
|
|
templateData: templateData
|
|
}, function(err, result) {
|
|
return next(err, result);
|
|
});
|
|
} else {
|
|
return next(null, content);
|
|
}
|
|
});
|
|
};
|
|
|
|
DocumentModel.prototype.render = function(opts, next) {
|
|
var contentRenderedWithoutLayouts, file, fullPath, tasks, _base, _base1, _ref1, _ref2, _ref3, _ref4, _ref5;
|
|
|
|
if (opts == null) {
|
|
opts = {};
|
|
}
|
|
file = this;
|
|
contentRenderedWithoutLayouts = null;
|
|
fullPath = this.get('fullPath');
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
opts = extendr.clone(opts || {});
|
|
if ((_ref2 = opts.actions) == null) {
|
|
opts.actions = ['renderExtensions', 'renderDocument', 'renderLayouts'];
|
|
}
|
|
if ((_ref3 = opts.content) == null) {
|
|
opts.content = this.get('body');
|
|
}
|
|
opts.templateData = extendr.clone(opts.templateData || {});
|
|
if ((_ref4 = (_base = opts.templateData).document) == null) {
|
|
_base.document = file.toJSON();
|
|
}
|
|
if ((_ref5 = (_base1 = opts.templateData).documentModel) == null) {
|
|
_base1.documentModel = file;
|
|
}
|
|
file.log('debug', "Rendering the file: " + fullPath);
|
|
tasks = new TaskGroup().once('complete', function(err) {
|
|
var contentRendered, rendered;
|
|
|
|
if (err) {
|
|
file.log('warn', "Something went wrong while rendering: " + fullPath);
|
|
return next(err, opts.content, file);
|
|
}
|
|
contentRendered = opts.content;
|
|
if (contentRenderedWithoutLayouts == null) {
|
|
contentRenderedWithoutLayouts = contentRendered;
|
|
}
|
|
rendered = true;
|
|
file.set({
|
|
contentRendered: contentRendered,
|
|
contentRenderedWithoutLayouts: contentRenderedWithoutLayouts,
|
|
rendered: rendered
|
|
});
|
|
file.log('debug', "Rendering completed for: " + fullPath);
|
|
return next(null, opts.content, file);
|
|
});
|
|
if (__indexOf.call(opts.actions, 'renderExtensions') >= 0) {
|
|
tasks.addTask(function(complete) {
|
|
return file.renderExtensions(opts, function(err, result) {
|
|
if (err) {
|
|
return complete(err);
|
|
}
|
|
opts.content = result;
|
|
return complete();
|
|
});
|
|
});
|
|
}
|
|
if (__indexOf.call(opts.actions, 'renderDocument') >= 0) {
|
|
tasks.addTask(function(complete) {
|
|
return file.renderDocument(opts, function(err, result) {
|
|
if (err) {
|
|
return complete(err);
|
|
}
|
|
opts.content = result;
|
|
contentRenderedWithoutLayouts = result;
|
|
return complete();
|
|
});
|
|
});
|
|
}
|
|
if (__indexOf.call(opts.actions, 'renderLayouts') >= 0) {
|
|
tasks.addTask(function(complete) {
|
|
return file.renderLayouts(opts, function(err, result) {
|
|
if (err) {
|
|
return complete(err);
|
|
}
|
|
opts.content = result;
|
|
return complete();
|
|
});
|
|
});
|
|
}
|
|
tasks.run();
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.writeRendered = function(opts, next) {
|
|
var file, _ref1;
|
|
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
file = this;
|
|
opts.content || (opts.content = this.getOutContent());
|
|
opts.type || (opts.type = 'rendered document');
|
|
this.write(opts, next);
|
|
return this;
|
|
};
|
|
|
|
DocumentModel.prototype.writeSource = function(opts, next) {
|
|
var body, content, file, fullPath, header, meta, metaData, parser, seperator, source, _ref1;
|
|
|
|
_ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
|
|
file = this;
|
|
meta = this.getMeta();
|
|
if (!CSON) {
|
|
CSON = require('cson');
|
|
}
|
|
fullPath = this.get('fullPath');
|
|
content = (this.getContent() || '').toString();
|
|
parser = 'cson';
|
|
seperator = '---';
|
|
file.log('debug', "Writing the source file: " + fullPath);
|
|
metaData = meta.toJSON();
|
|
header = CSON.stringifySync(metaData);
|
|
content = body = content.replace(/^\s+/, '');
|
|
source = "" + seperator + " " + parser + "\n" + header + "\n" + seperator + "\n\n" + body;
|
|
this.set({
|
|
parser: parser,
|
|
header: header,
|
|
body: body,
|
|
content: content,
|
|
source: source
|
|
});
|
|
opts.path || (opts.path = fullPath);
|
|
opts.content || (opts.content = content);
|
|
opts.type || (opts.type = 'source document');
|
|
this.write(opts, next);
|
|
return this;
|
|
};
|
|
|
|
return DocumentModel;
|
|
|
|
})(FileModel);
|
|
|
|
module.exports = DocumentModel;
|