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

  1. // Generated by CoffeeScript 1.6.2
  2. var CSON, DocumentModel, FileModel, TaskGroup, YAML, eachr, extendr, mime, pathUtil, _ref,
  3. __hasProp = {}.hasOwnProperty,
  4. __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; },
  5. __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; };
  6. pathUtil = require('path');
  7. extendr = require('extendr');
  8. eachr = require('eachr');
  9. TaskGroup = require('taskgroup').TaskGroup;
  10. mime = require('mime');
  11. CSON = null;
  12. YAML = null;
  13. FileModel = require(__dirname + '/file');
  14. DocumentModel = (function(_super) {
  15. __extends(DocumentModel, _super);
  16. function DocumentModel() {
  17. _ref = DocumentModel.__super__.constructor.apply(this, arguments);
  18. return _ref;
  19. }
  20. DocumentModel.prototype.type = 'document';
  21. DocumentModel.prototype.defaults = {
  22. referencesOthers: false,
  23. header: null,
  24. parser: null,
  25. body: null,
  26. rendered: false,
  27. contentRendered: null,
  28. contentRenderedWithoutLayouts: null,
  29. dynamic: false,
  30. tags: null,
  31. renderSingleExtensions: false
  32. };
  33. DocumentModel.prototype.getOutContent = function() {
  34. var content;
  35. content = this.get('contentRendered') || this.get('content') || this.getBuffer();
  36. return content;
  37. };
  38. DocumentModel.prototype.toJSON = function() {
  39. var data;
  40. data = DocumentModel.__super__.toJSON.apply(this, arguments);
  41. data.meta = this.getMeta().toJSON();
  42. return data;
  43. };
  44. DocumentModel.prototype.referencesOthers = function(flag) {
  45. if (flag == null) {
  46. flag = true;
  47. }
  48. this.set({
  49. referencesOthers: flag
  50. });
  51. return this;
  52. };
  53. DocumentModel.prototype.parse = function(opts, next) {
  54. var buffer, key, meta, reset, value, _ref1, _ref2,
  55. _this = this;
  56. if (opts == null) {
  57. opts = {};
  58. }
  59. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  60. buffer = this.getBuffer();
  61. meta = this.getMeta();
  62. reset = {};
  63. _ref2 = meta.attributes;
  64. for (key in _ref2) {
  65. if (!__hasProp.call(_ref2, key)) continue;
  66. value = _ref2[key];
  67. reset[key] = this.defaults[key];
  68. }
  69. reset = extendr.dereference(reset);
  70. this.set(reset);
  71. meta.clear();
  72. DocumentModel.__super__.parse.call(this, opts, function() {
  73. var body, content, err, header, ignored, match, metaData, metaDate, metaUrl, metaUrls, parser, regex, seperator;
  74. content = _this.get('content').replace(/\r\n?/gm, '\n');
  75. regex = /^\s*(([^\s\d\w])\2{2,})(?:\x20*([a-z]+))?([\s\S]*?)\1/;
  76. match = regex.exec(content);
  77. metaData = {};
  78. if (match) {
  79. seperator = match[1];
  80. parser = match[3] || 'yaml';
  81. header = match[4].trim();
  82. body = content.substring(match[0].length).trim();
  83. try {
  84. switch (parser) {
  85. case 'cson':
  86. case 'coffee':
  87. case 'coffeescript':
  88. case 'coffee-script':
  89. if (!CSON) {
  90. CSON = require('cson');
  91. }
  92. metaData = CSON.parseSync(header);
  93. meta.set(metaData);
  94. break;
  95. case 'yaml':
  96. if (!YAML) {
  97. YAML = require('yamljs');
  98. }
  99. metaData = YAML.parse(header.replace(/\t/g, ' '));
  100. meta.set(metaData);
  101. break;
  102. default:
  103. err = new Error("Unknown meta parser: " + parser);
  104. return next(err);
  105. }
  106. } catch (_error) {
  107. err = _error;
  108. return next(err);
  109. }
  110. } else {
  111. body = content;
  112. }
  113. if (metaData.encoding && metaData.encoding !== _this.get('encoding')) {
  114. _this.setMeta({
  115. encoding: metaData.encoding
  116. });
  117. opts.reencode = true;
  118. return _this.parse(opts, next);
  119. }
  120. body = body.replace(/^\n+/, '');
  121. _this.set({
  122. source: content,
  123. content: body,
  124. header: header,
  125. body: body,
  126. parser: parser,
  127. name: _this.get('name') || _this.get('title') || _this.get('basename')
  128. });
  129. metaDate = meta.get('date');
  130. if (metaDate) {
  131. metaDate = new Date(metaDate);
  132. meta.set({
  133. date: metaDate
  134. });
  135. }
  136. ignored = meta.get('ignored') || meta.get('ignore') || meta.get('skip') || meta.get('draft') || (meta.get('published') === false);
  137. if (ignored) {
  138. meta.set({
  139. ignored: true
  140. });
  141. }
  142. metaUrls = meta.get('urls');
  143. metaUrl = meta.get('url');
  144. if (metaUrls) {
  145. _this.addUrl(metaUrls);
  146. }
  147. if (metaUrl) {
  148. _this.addUrl(metaUrl);
  149. }
  150. _this.set(meta.toJSON());
  151. return next();
  152. });
  153. return this;
  154. };
  155. DocumentModel.prototype.normalize = function(opts, next) {
  156. var _ref1,
  157. _this = this;
  158. if (opts == null) {
  159. opts = {};
  160. }
  161. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  162. DocumentModel.__super__.normalize.call(this, opts, function() {
  163. var extensions, outExtension;
  164. extensions = _this.get('extensions');
  165. if ((extensions != null) && extensions.length) {
  166. outExtension = extensions[0];
  167. _this.set({
  168. outExtension: outExtension
  169. });
  170. }
  171. return next();
  172. });
  173. return this;
  174. };
  175. DocumentModel.prototype.contextualize = function(opts, next) {
  176. var _ref1,
  177. _this = this;
  178. if (opts == null) {
  179. opts = {};
  180. }
  181. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  182. DocumentModel.__super__.contextualize.call(this, opts, function() {
  183. return _this.getEve(function(err, eve) {
  184. var basename, changes, extensions, fullPath, meta, name, outContentType, outExtension, outFilename, outPath, relativeDirPath, relativeOutPath, url;
  185. if (err) {
  186. return next(err);
  187. }
  188. changes = {};
  189. meta = _this.getMeta();
  190. fullPath = _this.get('fullPath');
  191. basename = _this.get('basename');
  192. relativeDirPath = _this.get('relativeDirPath');
  193. extensions = _this.get('extensions');
  194. outExtension = _this.get('outExtension');
  195. url = meta.get('url') || null;
  196. name = meta.get('name') || null;
  197. outPath = meta.get('outPath') || null;
  198. outFilename = null;
  199. if (eve != null) {
  200. outExtension = eve.get('outExtension');
  201. }
  202. if (basename && outExtension) {
  203. if (basename[0] === '.' && outExtension === extensions[0]) {
  204. outFilename = basename;
  205. } else {
  206. outFilename = "" + basename + "." + outExtension;
  207. }
  208. changes.outFilename = outFilename;
  209. }
  210. if (outFilename) {
  211. if (relativeDirPath) {
  212. relativeOutPath = "" + relativeDirPath + "/" + outFilename;
  213. } else {
  214. relativeOutPath = "" + outFilename;
  215. }
  216. changes.relativeOutPath = relativeOutPath;
  217. if (!url) {
  218. changes.url = url = "/" + relativeOutPath;
  219. }
  220. }
  221. if (!name && (outFilename != null)) {
  222. changes.name = name = outFilename;
  223. }
  224. if (_this.outDirPath && relativeOutPath) {
  225. changes.outPath = outPath = pathUtil.join(_this.outDirPath, relativeOutPath);
  226. }
  227. if (url) {
  228. _this.removeUrl(_this.get('url'));
  229. _this.setUrl(url);
  230. }
  231. if (outPath || fullPath) {
  232. changes.outContentType = outContentType = mime.lookup(outPath || fullPath);
  233. }
  234. _this.set(changes);
  235. return next();
  236. });
  237. });
  238. return this;
  239. };
  240. DocumentModel.prototype.hasLayout = function() {
  241. return this.get('layout') != null;
  242. };
  243. DocumentModel.prototype.getLayout = function(next) {
  244. var file, layoutSelector;
  245. file = this;
  246. layoutSelector = this.get('layout');
  247. if (!layoutSelector) {
  248. return next(null, null);
  249. }
  250. this.emit('getLayout', {
  251. selector: layoutSelector
  252. }, function(err, opts) {
  253. var layout;
  254. layout = opts.layout;
  255. if (err) {
  256. file.set({
  257. 'layoutId': null
  258. });
  259. return next(err);
  260. } else if (!layout) {
  261. file.set({
  262. 'layoutId': null
  263. });
  264. err = new Error("Could not find the specified layout: " + layoutSelector);
  265. return next(err);
  266. } else {
  267. file.set({
  268. 'layoutId': layout.id
  269. });
  270. return next(null, layout);
  271. }
  272. });
  273. return this;
  274. };
  275. DocumentModel.prototype.getEve = function(next) {
  276. if (this.hasLayout()) {
  277. this.getLayout(function(err, layout) {
  278. if (err) {
  279. return next(err, null);
  280. } else {
  281. return layout.getEve(next);
  282. }
  283. });
  284. } else {
  285. next(null, this);
  286. }
  287. return this;
  288. };
  289. DocumentModel.prototype.renderExtensions = function(opts, next) {
  290. var content, extension, extensions, extensionsReversed, file, filename, renderSingleExtensions, result, tasks, templateData, _i, _len;
  291. file = this;
  292. extensions = this.get('extensions');
  293. filename = this.get('filename');
  294. content = opts.content, templateData = opts.templateData, renderSingleExtensions = opts.renderSingleExtensions;
  295. if (content == null) {
  296. content = this.get('body');
  297. }
  298. if (templateData == null) {
  299. templateData = {};
  300. }
  301. if (renderSingleExtensions == null) {
  302. renderSingleExtensions = this.get('renderSingleExtensions');
  303. }
  304. result = content;
  305. extensionsReversed = [];
  306. if (extensions.length === 0 && filename) {
  307. extensionsReversed.push(filename);
  308. }
  309. for (_i = 0, _len = extensions.length; _i < _len; _i++) {
  310. extension = extensions[_i];
  311. extensionsReversed.unshift(extension);
  312. }
  313. if (renderSingleExtensions && extensionsReversed.length === 1) {
  314. if (renderSingleExtensions !== 'auto' || filename.replace(/^\./, '') === extensionsReversed[0]) {
  315. extensionsReversed.push(null);
  316. }
  317. }
  318. if (extensionsReversed.length <= 1) {
  319. return next(null, result);
  320. }
  321. tasks = new TaskGroup().once('complete', function(err) {
  322. return next(err, result);
  323. });
  324. eachr(extensionsReversed.slice(1), function(extension, index) {
  325. return tasks.addTask(function(complete) {
  326. var eventData;
  327. eventData = {
  328. inExtension: extensionsReversed[index],
  329. outExtension: extension,
  330. templateData: templateData,
  331. file: file,
  332. content: result
  333. };
  334. return file.trigger('render', eventData, function(err) {
  335. var message;
  336. if (err) {
  337. return complete(err);
  338. }
  339. if (result && result === eventData.content) {
  340. 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";
  341. file.log('warn', message);
  342. return complete();
  343. }
  344. result = eventData.content;
  345. return complete();
  346. });
  347. });
  348. });
  349. tasks.run();
  350. return this;
  351. };
  352. DocumentModel.prototype.renderDocument = function(opts, next) {
  353. var content, eventData, extension, file, templateData, _ref1;
  354. file = this;
  355. extension = this.get('extensions')[0];
  356. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  357. content = opts.content, templateData = opts.templateData;
  358. if (content == null) {
  359. content = this.get('body');
  360. }
  361. if (templateData == null) {
  362. templateData = {};
  363. }
  364. eventData = {
  365. extension: extension,
  366. templateData: templateData,
  367. file: file,
  368. content: content
  369. };
  370. file.trigger('renderDocument', eventData, function(err) {
  371. return next(err, eventData.content);
  372. });
  373. return this;
  374. };
  375. DocumentModel.prototype.renderLayouts = function(opts, next) {
  376. var content, file, templateData, _ref1;
  377. file = this;
  378. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  379. content = opts.content, templateData = opts.templateData;
  380. if (content == null) {
  381. content = this.get('body');
  382. }
  383. if (templateData == null) {
  384. templateData = {};
  385. }
  386. return file.getLayout(function(err, layout) {
  387. if (err) {
  388. return next(err, content);
  389. }
  390. if (layout) {
  391. templateData.content = content;
  392. return layout.render({
  393. templateData: templateData
  394. }, function(err, result) {
  395. return next(err, result);
  396. });
  397. } else {
  398. return next(null, content);
  399. }
  400. });
  401. };
  402. DocumentModel.prototype.render = function(opts, next) {
  403. var contentRenderedWithoutLayouts, file, fullPath, tasks, _base, _base1, _ref1, _ref2, _ref3, _ref4, _ref5;
  404. if (opts == null) {
  405. opts = {};
  406. }
  407. file = this;
  408. contentRenderedWithoutLayouts = null;
  409. fullPath = this.get('fullPath');
  410. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  411. opts = extendr.clone(opts || {});
  412. if ((_ref2 = opts.actions) == null) {
  413. opts.actions = ['renderExtensions', 'renderDocument', 'renderLayouts'];
  414. }
  415. if ((_ref3 = opts.content) == null) {
  416. opts.content = this.get('body');
  417. }
  418. opts.templateData = extendr.clone(opts.templateData || {});
  419. if ((_ref4 = (_base = opts.templateData).document) == null) {
  420. _base.document = file.toJSON();
  421. }
  422. if ((_ref5 = (_base1 = opts.templateData).documentModel) == null) {
  423. _base1.documentModel = file;
  424. }
  425. file.log('debug', "Rendering the file: " + fullPath);
  426. tasks = new TaskGroup().once('complete', function(err) {
  427. var contentRendered, rendered;
  428. if (err) {
  429. file.log('warn', "Something went wrong while rendering: " + fullPath);
  430. return next(err, opts.content, file);
  431. }
  432. contentRendered = opts.content;
  433. if (contentRenderedWithoutLayouts == null) {
  434. contentRenderedWithoutLayouts = contentRendered;
  435. }
  436. rendered = true;
  437. file.set({
  438. contentRendered: contentRendered,
  439. contentRenderedWithoutLayouts: contentRenderedWithoutLayouts,
  440. rendered: rendered
  441. });
  442. file.log('debug', "Rendering completed for: " + fullPath);
  443. return next(null, opts.content, file);
  444. });
  445. if (__indexOf.call(opts.actions, 'renderExtensions') >= 0) {
  446. tasks.addTask(function(complete) {
  447. return file.renderExtensions(opts, function(err, result) {
  448. if (err) {
  449. return complete(err);
  450. }
  451. opts.content = result;
  452. return complete();
  453. });
  454. });
  455. }
  456. if (__indexOf.call(opts.actions, 'renderDocument') >= 0) {
  457. tasks.addTask(function(complete) {
  458. return file.renderDocument(opts, function(err, result) {
  459. if (err) {
  460. return complete(err);
  461. }
  462. opts.content = result;
  463. contentRenderedWithoutLayouts = result;
  464. return complete();
  465. });
  466. });
  467. }
  468. if (__indexOf.call(opts.actions, 'renderLayouts') >= 0) {
  469. tasks.addTask(function(complete) {
  470. return file.renderLayouts(opts, function(err, result) {
  471. if (err) {
  472. return complete(err);
  473. }
  474. opts.content = result;
  475. return complete();
  476. });
  477. });
  478. }
  479. tasks.run();
  480. return this;
  481. };
  482. DocumentModel.prototype.writeRendered = function(opts, next) {
  483. var file, _ref1;
  484. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  485. file = this;
  486. opts.content || (opts.content = this.getOutContent());
  487. opts.type || (opts.type = 'rendered document');
  488. this.write(opts, next);
  489. return this;
  490. };
  491. DocumentModel.prototype.writeSource = function(opts, next) {
  492. var body, content, file, fullPath, header, meta, metaData, parser, seperator, source, _ref1;
  493. _ref1 = this.getActionArgs(opts, next), opts = _ref1.opts, next = _ref1.next;
  494. file = this;
  495. meta = this.getMeta();
  496. if (!CSON) {
  497. CSON = require('cson');
  498. }
  499. fullPath = this.get('fullPath');
  500. content = (this.getContent() || '').toString();
  501. parser = 'cson';
  502. seperator = '---';
  503. file.log('debug', "Writing the source file: " + fullPath);
  504. metaData = meta.toJSON();
  505. header = CSON.stringifySync(metaData);
  506. content = body = content.replace(/^\s+/, '');
  507. source = "" + seperator + " " + parser + "\n" + header + "\n" + seperator + "\n\n" + body;
  508. this.set({
  509. parser: parser,
  510. header: header,
  511. body: body,
  512. content: content,
  513. source: source
  514. });
  515. opts.path || (opts.path = fullPath);
  516. opts.content || (opts.content = content);
  517. opts.type || (opts.type = 'source document');
  518. this.write(opts, next);
  519. return this;
  520. };
  521. return DocumentModel;
  522. })(FileModel);
  523. module.exports = DocumentModel;