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.

3661 lines
108 KiB

  1. // Generated by CoffeeScript 1.6.2
  2. var Backbone, BasePlugin, CSON, Collection, DocPad, DocumentModel, ElementsCollection, EventEmitterEnhanced, Events, FileModel, FilesCollection, MetaCollection, Model, PluginLoader, QueryCollection, ScriptsCollection, StylesCollection, TaskGroup, View, ambi, balUtil, canihaz, eachr, extendr, pathUtil, queryEngine, safefs, typeChecker, util, _, _ref,
  3. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4. __hasProp = {}.hasOwnProperty,
  5. __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; },
  6. __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; },
  7. __slice = [].slice;
  8. pathUtil = require('path');
  9. _ = require('lodash');
  10. CSON = require('cson');
  11. balUtil = require('bal-util');
  12. extendr = require('extendr');
  13. eachr = require('eachr');
  14. typeChecker = require('typechecker');
  15. ambi = require('ambi');
  16. TaskGroup = require('taskgroup').TaskGroup;
  17. safefs = require('safefs');
  18. util = require('util');
  19. canihaz = null;
  20. EventEmitterEnhanced = balUtil.EventEmitterEnhanced;
  21. _ref = require(__dirname + '/base'), queryEngine = _ref.queryEngine, Backbone = _ref.Backbone, Events = _ref.Events, Model = _ref.Model, Collection = _ref.Collection, View = _ref.View, QueryCollection = _ref.QueryCollection;
  22. FileModel = require(__dirname + '/models/file');
  23. DocumentModel = require(__dirname + '/models/document');
  24. FilesCollection = require(__dirname + '/collections/files');
  25. ElementsCollection = require(__dirname + '/collections/elements');
  26. MetaCollection = require(__dirname + '/collections/meta');
  27. ScriptsCollection = require(__dirname + '/collections/scripts');
  28. StylesCollection = require(__dirname + '/collections/styles');
  29. PluginLoader = require(__dirname + '/plugin-loader');
  30. BasePlugin = require(__dirname + '/plugin');
  31. /*
  32. The DocPad Class
  33. It extends the EventSystem from bal-util to provide system events
  34. It allows us to support multiple instances of docpad at the same time
  35. */
  36. DocPad = (function(_super) {
  37. __extends(DocPad, _super);
  38. DocPad.prototype.Events = Events;
  39. DocPad.prototype.Model = Model;
  40. DocPad.prototype.Collection = Collection;
  41. DocPad.prototype.View = View;
  42. DocPad.prototype.QueryCollection = QueryCollection;
  43. DocPad.prototype.FileModel = FileModel;
  44. DocPad.prototype.DocumentModel = DocumentModel;
  45. DocPad.prototype.FilesCollection = FilesCollection;
  46. DocPad.prototype.ElementsCollection = ElementsCollection;
  47. DocPad.prototype.MetaCollection = MetaCollection;
  48. DocPad.prototype.ScriptsCollection = ScriptsCollection;
  49. DocPad.prototype.StylesCollection = StylesCollection;
  50. DocPad.prototype.PluginLoader = PluginLoader;
  51. DocPad.prototype.BasePlugin = BasePlugin;
  52. DocPad.prototype.growlInstance = null;
  53. DocPad.prototype.getGrowlInstance = function() {
  54. var err;
  55. if ((this.growlInstance != null) === false) {
  56. if (this.getConfig().growl) {
  57. try {
  58. this.growlInstance = require('growl');
  59. } catch (_error) {
  60. err = _error;
  61. this.growlInstance = false;
  62. }
  63. } else {
  64. this.growlInstance = false;
  65. }
  66. }
  67. return this.growlInstance;
  68. };
  69. DocPad.prototype.mixpanelInstance = null;
  70. DocPad.prototype.getMixpanelInstance = function() {
  71. var config, err, mixpanelToken, reportStatistics;
  72. if ((this.mixpanelInstance != null) === false) {
  73. config = this.getConfig();
  74. reportStatistics = config.reportStatistics, mixpanelToken = config.mixpanelToken;
  75. if ((reportStatistics != null) && (mixpanelToken != null)) {
  76. if (reportStatistics && mixpanelToken) {
  77. try {
  78. this.mixpanelInstance = require('mixpanel').init(mixpanelToken);
  79. } catch (_error) {
  80. err = _error;
  81. this.mixpanelInstance = false;
  82. }
  83. } else {
  84. this.mixpanelInstance = false;
  85. }
  86. } else {
  87. this.mixpanelInstance = null;
  88. }
  89. }
  90. return this.mixpanelInstance;
  91. };
  92. DocPad.prototype.airbrakeInstance = null;
  93. DocPad.prototype.getAirbrakeInstance = function() {
  94. var airbrakeToken, config, err, reportErrors;
  95. if ((this.airbrakeInstance != null) === false) {
  96. config = this.getConfig();
  97. airbrakeToken = config.airbrakeToken, reportErrors = config.reportErrors;
  98. if (reportErrors === true && /win/.test(process.platform) === false) {
  99. try {
  100. this.airbrakeInstance = require('airbrake').createClientairbrakeToken();
  101. } catch (_error) {
  102. err = _error;
  103. this.airbrakeInstance = false;
  104. }
  105. } else {
  106. this.airbrakeInstance = false;
  107. }
  108. }
  109. return this.airbrakeInstance;
  110. };
  111. DocPad.prototype.version = null;
  112. DocPad.prototype.getVersion = function() {
  113. return this.version;
  114. };
  115. DocPad.prototype.getProcessPlatform = function() {
  116. return process.platform;
  117. };
  118. DocPad.prototype.getProcessVersion = function() {
  119. return process.version.replace(/^v/, '');
  120. };
  121. DocPad.prototype.serverExpress = null;
  122. DocPad.prototype.serverHttp = null;
  123. DocPad.prototype.getServer = function(both) {
  124. var serverExpress, serverHttp;
  125. serverExpress = this.serverExpress, serverHttp = this.serverHttp;
  126. if (both) {
  127. return {
  128. serverExpress: serverExpress,
  129. serverHttp: serverHttp
  130. };
  131. } else {
  132. return serverExpress;
  133. }
  134. };
  135. DocPad.prototype.setServer = function(servers) {
  136. this.serverExpress = servers.serverExpress;
  137. return this.serverHttp = servers.serverHttp;
  138. };
  139. DocPad.prototype.loggerInstances = null;
  140. DocPad.prototype.getLogger = function() {
  141. var _ref1;
  142. return (_ref1 = this.loggerInstances) != null ? _ref1.logger : void 0;
  143. };
  144. DocPad.prototype.getLoggers = function() {
  145. return this.loggerInstances;
  146. };
  147. DocPad.prototype.setLoggers = function(loggers) {
  148. if (this.loggerInstances) {
  149. this.warn('Loggers have already been set');
  150. } else {
  151. this.loggerInstances = loggers;
  152. }
  153. return loggers;
  154. };
  155. DocPad.prototype.actionRunnerInstance = null;
  156. DocPad.prototype.getActionRunner = function() {
  157. return this.actionRunnerInstance;
  158. };
  159. DocPad.prototype.errorRunnerInstance = null;
  160. DocPad.prototype.getErrorRunner = function() {
  161. return this.errorRunnerInstance;
  162. };
  163. DocPad.prototype.trackRunnerInstance = null;
  164. DocPad.prototype.getTrackRunner = function() {
  165. return this.trackRunnerInstance;
  166. };
  167. DocPad.prototype.events = ['extendTemplateData', 'extendCollections', 'docpadLoaded', 'docpadReady', 'consoleSetup', 'generateBefore', 'populateCollections', 'generateAfter', 'parseBefore', 'parseAfter', 'contextualizeBefore', 'contextualizeAfter', 'renderBefore', 'render', 'renderDocument', 'renderAfter', 'writeBefore', 'writeAfter', 'serverBefore', 'serverExtend', 'serverAfter'];
  168. DocPad.prototype.getEvents = function() {
  169. return this.events;
  170. };
  171. DocPad.prototype.database = null;
  172. DocPad.prototype.databaseCache = null;
  173. DocPad.prototype.getDatabase = function() {
  174. return this.database;
  175. };
  176. DocPad.prototype.getDatabaseCache = function() {
  177. return this.databaseCache || this.database;
  178. };
  179. DocPad.prototype.filesByUrl = null;
  180. DocPad.prototype.filesBySelector = null;
  181. DocPad.prototype.filesByOutPath = null;
  182. DocPad.prototype.blocks = null;
  183. /* {
  184. # A collection of meta elements
  185. meta: null # Elements Collection
  186. # A collection of script elements
  187. scripts: null # Scripts Collection
  188. # Collection of style elements
  189. styles: null # Styles Collection
  190. }
  191. */
  192. DocPad.prototype.getBlock = function(name, clone) {
  193. var block, classname;
  194. block = this.blocks[name];
  195. if (clone) {
  196. classname = name[0].toUpperCase() + name.slice(1) + 'Collection';
  197. block = new this[classname](block.models);
  198. }
  199. return block;
  200. };
  201. DocPad.prototype.setBlock = function(name, value) {
  202. if (this.blocks[name] != null) {
  203. this.blocks[name].destroy();
  204. if (value) {
  205. this.blocks[name] = value;
  206. } else {
  207. delete this.blocks[name];
  208. }
  209. } else {
  210. this.blocks[name] = value;
  211. }
  212. return this;
  213. };
  214. DocPad.prototype.getBlocks = function(blocks) {
  215. this.blocks;
  216. return this;
  217. };
  218. DocPad.prototype.setBlocks = function(blocks) {
  219. var name, value;
  220. for (name in blocks) {
  221. if (!__hasProp.call(blocks, name)) continue;
  222. value = blocks[name];
  223. this.setBlock(name, value);
  224. }
  225. return this;
  226. };
  227. DocPad.prototype.collections = null;
  228. /* {
  229. # Documents collection
  230. documents: null # QueryEngine Collection
  231. # Files collection
  232. files: null # QueryEngine Collection
  233. # Layouts collection
  234. layouts: null # QueryEngine Collection
  235. }
  236. */
  237. DocPad.prototype.getCollection = function(name) {
  238. return this.collections[name];
  239. };
  240. DocPad.prototype.setCollection = function(name, value) {
  241. if (this.collections[name] != null) {
  242. this.collections[name].destroy();
  243. if (value) {
  244. this.collections[name] = value;
  245. } else {
  246. delete this.collections[name];
  247. }
  248. } else {
  249. this.collections[name] = value;
  250. }
  251. return this;
  252. };
  253. DocPad.prototype.getCollections = function() {
  254. return this.collections;
  255. };
  256. DocPad.prototype.setCollections = function(collections) {
  257. var name, value;
  258. for (name in collections) {
  259. if (!__hasProp.call(collections, name)) continue;
  260. value = collections[name];
  261. this.setCollection(name, value);
  262. }
  263. return this;
  264. };
  265. DocPad.prototype.getFiles = function(query, sorting, paging) {
  266. var files, key;
  267. key = JSON.stringify({
  268. query: query,
  269. sorting: sorting,
  270. paging: paging
  271. });
  272. files = this.getCollection(key);
  273. if (!files) {
  274. files = this.getDatabase().findAllLive(query, sorting, paging);
  275. this.setCollection(key, files);
  276. }
  277. return files;
  278. };
  279. DocPad.prototype.getFile = function(query, sorting, paging) {
  280. var file;
  281. file = this.getDatabase().findOne(query, sorting, paging);
  282. return file;
  283. };
  284. DocPad.prototype.getFilesAtPath = function(path, sorting, paging) {
  285. var files, query;
  286. query = {
  287. $or: [
  288. {
  289. relativePath: {
  290. $startsWith: path
  291. }
  292. }, {
  293. fullPath: {
  294. $startsWith: path
  295. }
  296. }
  297. ]
  298. };
  299. files = this.getFiles(query, sorting, paging);
  300. return files;
  301. };
  302. DocPad.prototype.getFileAtPath = function(path, sorting, paging) {
  303. var file;
  304. file = this.getDatabase().fuzzyFindOne(path, sorting, paging);
  305. return file;
  306. };
  307. DocPad.prototype.getFileByUrl = function(url, opts) {
  308. var file, _ref1;
  309. if (opts == null) {
  310. opts = {};
  311. }
  312. if ((_ref1 = opts.collection) == null) {
  313. opts.collection = this.getDatabase();
  314. }
  315. file = opts.collection.get(this.filesByUrl[url]);
  316. return file;
  317. };
  318. DocPad.prototype.getFileBySelector = function(selector, opts) {
  319. var file, _ref1;
  320. if (opts == null) {
  321. opts = {};
  322. }
  323. if ((_ref1 = opts.collection) == null) {
  324. opts.collection = this.getDatabase();
  325. }
  326. file = opts.collection.get(this.filesBySelector[selector]);
  327. if (!file) {
  328. file = opts.collection.fuzzyFindOne(selector);
  329. if (file) {
  330. this.filesBySelector[selector] = file.id;
  331. }
  332. }
  333. return file;
  334. };
  335. DocPad.prototype.skeletonsCollection = null;
  336. DocPad.prototype.getSkeletons = function(next) {
  337. var docpad, locale;
  338. docpad = this;
  339. locale = this.getLocale();
  340. if (this.skeletonsCollection != null) {
  341. return next(null, this.skeletonsCollection);
  342. }
  343. this.skeletonsCollection = new Collection();
  344. this.skeletonsCollection.comparator = queryEngine.generateComparator({
  345. position: 1,
  346. name: 1
  347. });
  348. this.getExchange(function(err, exchange) {
  349. var index, skeleton, skeletonKey, _ref1, _ref2, _ref3, _ref4;
  350. if (err) {
  351. return next(err);
  352. }
  353. index = 0;
  354. _ref1 = exchange.skeletons;
  355. for (skeletonKey in _ref1) {
  356. if (!__hasProp.call(_ref1, skeletonKey)) continue;
  357. skeleton = _ref1[skeletonKey];
  358. if ((_ref2 = skeleton.id) == null) {
  359. skeleton.id = skeletonKey;
  360. }
  361. if ((_ref3 = skeleton.name) == null) {
  362. skeleton.name = skeletonKey;
  363. }
  364. if ((_ref4 = skeleton.position) == null) {
  365. skeleton.position = index;
  366. }
  367. docpad.skeletonsCollection.add(new Model(skeleton));
  368. ++index;
  369. }
  370. docpad.skeletonsCollection.add(new Model({
  371. id: 'none',
  372. name: locale.skeletonNoneName,
  373. description: locale.skeletonNoneDescription,
  374. position: Infinity
  375. }));
  376. return next(null, docpad.skeletonsCollection);
  377. });
  378. return this;
  379. };
  380. DocPad.prototype.slowPlugins = null;
  381. DocPad.prototype.loadedPlugins = null;
  382. DocPad.prototype.exchange = null;
  383. DocPad.prototype.corePath = pathUtil.join(__dirname, '..', '..');
  384. DocPad.prototype.libPath = __dirname;
  385. DocPad.prototype.mainPath = pathUtil.join(__dirname, 'docpad');
  386. DocPad.prototype.packagePath = pathUtil.join(__dirname, '..', '..', 'package.json');
  387. DocPad.prototype.localePath = pathUtil.join(__dirname, '..', '..', 'locale');
  388. DocPad.prototype.debugLogPath = pathUtil.join(process.cwd(), 'docpad-debug.log');
  389. DocPad.prototype.userConfigPath = '.docpad.cson';
  390. DocPad.prototype.initialTemplateData = null;
  391. DocPad.prototype.pluginsTemplateData = null;
  392. DocPad.prototype.getTemplateData = function(userTemplateData) {
  393. var docpad, locale, renderPasses, templateData, _base, _base1, _ref1;
  394. userTemplateData || (userTemplateData = {});
  395. docpad = this;
  396. renderPasses = this.config.renderPasses;
  397. locale = this.getLocale();
  398. if ((_ref1 = this.initialTemplateData) == null) {
  399. this.initialTemplateData = {
  400. site: {},
  401. getEnvironment: function() {
  402. return docpad.getEnvironment();
  403. },
  404. getEnvironments: function() {
  405. return docpad.getEnvironments();
  406. },
  407. referencesOthers: function(flag) {
  408. var document;
  409. document = this.getDocument();
  410. document.referencesOthers();
  411. return null;
  412. },
  413. getDocument: function() {
  414. return this.documentModel;
  415. },
  416. getPath: function(path, parentPath) {
  417. var document;
  418. document = this.getDocument();
  419. path = document.getPath(path, parentPath);
  420. return path;
  421. },
  422. getFiles: function(query, sorting, paging) {
  423. var result;
  424. this.referencesOthers();
  425. result = docpad.getFiles(query, sorting, paging);
  426. return result;
  427. },
  428. getFile: function(query, sorting, paging) {
  429. var result;
  430. this.referencesOthers();
  431. result = docpad.getFile(query, sorting, paging);
  432. return result;
  433. },
  434. getFilesAtPath: function(path, sorting, paging) {
  435. var result;
  436. this.referencesOthers();
  437. path = this.getPath(path);
  438. result = docpad.getFilesAtPath(path, sorting, paging);
  439. return result;
  440. },
  441. getFileAtPath: function(relativePath) {
  442. var path, result;
  443. this.referencesOthers();
  444. path = this.getPath(relativePath);
  445. result = docpad.getFileAtPath(path);
  446. return result;
  447. },
  448. getDatabase: function() {
  449. this.referencesOthers();
  450. return docpad.getDatabase();
  451. },
  452. getCollection: function(name) {
  453. this.referencesOthers();
  454. return docpad.getCollection(name);
  455. },
  456. getBlock: function(name) {
  457. return docpad.getBlock(name, true);
  458. },
  459. include: function(subRelativePath, strict) {
  460. var err, file;
  461. if (strict == null) {
  462. strict = true;
  463. }
  464. file = this.getFileAtPath(subRelativePath);
  465. if (file) {
  466. if (strict && file.get('rendered') === false) {
  467. if (renderPasses === 1) {
  468. docpad.warn(util.format(locale.renderedEarlyViaInclude, subRelativePath));
  469. }
  470. return null;
  471. }
  472. return file.getOutContent();
  473. } else {
  474. err = new Error(util.format(locale.includeFailed, subRelativePath));
  475. throw err;
  476. }
  477. }
  478. };
  479. }
  480. templateData = extendr.extend({}, this.initialTemplateData, this.pluginsTemplateData, this.config.templateData, userTemplateData);
  481. (_base = templateData.site).date || (_base.date = new Date());
  482. (_base1 = templateData.site).keywords || (_base1.keywords = []);
  483. if (typeChecker.isString(templateData.site.keywords)) {
  484. templateData.site.keywords = templateData.site.keywords.split(/,\s*/g);
  485. }
  486. return templateData;
  487. };
  488. DocPad.prototype.locales = {
  489. en: CSON.parseFileSync(pathUtil.join(__dirname, '..', '..', 'locale', 'en.cson'))
  490. };
  491. DocPad.prototype.locale = null;
  492. DocPad.prototype.localeCode = null;
  493. DocPad.prototype.getLocaleCode = function() {
  494. var localeCode, localeCodes, _i, _len;
  495. if ((this.localeCode != null) === false) {
  496. localeCode = null;
  497. localeCodes = [this.getConfig().localeCode, balUtil.getLocaleCode(), 'en_AU'];
  498. for (_i = 0, _len = localeCodes.length; _i < _len; _i++) {
  499. localeCode = localeCodes[_i];
  500. if (localeCode && (this.locales[localeCode] != null)) {
  501. break;
  502. }
  503. }
  504. this.localeCode = localeCode.toLowerCase();
  505. }
  506. return this.localeCode;
  507. };
  508. DocPad.prototype.getLanguageCode = function() {
  509. var languageCode;
  510. if ((this.languageCode != null) === false) {
  511. languageCode = balUtil.getLanguageCode(this.getLocaleCode());
  512. this.languageCode = languageCode.toLowerCase();
  513. }
  514. return this.languageCode;
  515. };
  516. DocPad.prototype.getCountryCode = function() {
  517. var countryCode;
  518. if ((this.countryCode != null) === false) {
  519. countryCode = balUtil.getCountryCode(this.getLocaleCode());
  520. this.countryCode = countryCode.toLowerCase();
  521. }
  522. return this.countryCode;
  523. };
  524. DocPad.prototype.getLocale = function() {
  525. if ((this.locale != null) === false) {
  526. this.locale = this.locales[this.getLocaleCode()] || this.locales[this.getLanguageCode()] || this.locales['en'];
  527. }
  528. return this.locale;
  529. };
  530. DocPad.prototype.getEnvironment = function() {
  531. var env;
  532. env = this.getConfig().env || 'development';
  533. return env;
  534. };
  535. DocPad.prototype.getEnvironments = function() {
  536. var env, envs;
  537. env = this.getEnvironment();
  538. envs = env.split(/[, ]+/);
  539. return envs;
  540. };
  541. DocPad.prototype.websitePackageConfig = null;
  542. DocPad.prototype.config = null;
  543. DocPad.prototype.instanceConfig = null;
  544. DocPad.prototype.websiteConfig = null;
  545. DocPad.prototype.userConfig = {
  546. name: null,
  547. email: null,
  548. username: null,
  549. subscribed: null,
  550. subscribeTryAgain: null
  551. };
  552. DocPad.prototype.initialConfig = {
  553. force: false,
  554. enableUnlistedPlugins: true,
  555. enabledPlugins: {},
  556. skipUnsupportedPlugins: true,
  557. plugins: {},
  558. exchangeUrl: 'https://docpad.org/exchange.json',
  559. rootPath: process.cwd(),
  560. packagePath: 'package.json',
  561. latestPackageUrl: 'https://docpad.org/latest.json',
  562. configPaths: ['docpad.js', 'docpad.coffee', 'docpad.json', 'docpad.cson'],
  563. pluginPaths: [],
  564. pluginsPaths: ['node_modules', 'plugins'],
  565. reloadPaths: [],
  566. regeneratePaths: [],
  567. regenerateDelay: 100,
  568. outPath: 'out',
  569. srcPath: 'src',
  570. documentsPaths: ['documents'],
  571. filesPaths: ['files', 'public'],
  572. layoutsPaths: ['layouts'],
  573. ignorePaths: false,
  574. ignoreHiddenFiles: false,
  575. ignoreCommonPatterns: true,
  576. ignoreCustomPatterns: false,
  577. watchOptions: null,
  578. port: null,
  579. maxAge: 86400000,
  580. serverExpress: null,
  581. serverHttp: null,
  582. extendServer: true,
  583. middlewareStandard: true,
  584. middlewareBodyParser: true,
  585. middlewareMethodOverride: true,
  586. middlewareExpressRouter: true,
  587. middleware404: true,
  588. middleware500: true,
  589. logLevel: ((__indexOf.call(process.argv, '-d') >= 0) ? 7 : 6),
  590. logger: null,
  591. growl: true,
  592. catchExceptions: true,
  593. reportErrors: process.argv.join('').indexOf('test') === -1,
  594. reportStatistics: process.argv.join('').indexOf('test') === -1,
  595. hashKey: '7>9}$3hP86o,4=@T',
  596. airbrakeToken: 'e7374dd1c5a346efe3895b9b0c1c0325',
  597. mixpanelToken: 'd0f9b33c0ec921350b5419352028577e',
  598. detectEncoding: false,
  599. renderSingleExtensions: false,
  600. renderPasses: 1,
  601. checkVersion: false,
  602. welcome: false,
  603. prompts: false,
  604. helperUrl: 'https://docpad.org/helper/',
  605. safeMode: false,
  606. templateData: {},
  607. collections: {},
  608. events: {},
  609. regenerateEvery: false,
  610. localeCode: null,
  611. env: null,
  612. environments: {
  613. development: {
  614. maxAge: false,
  615. checkVersion: process.argv.length >= 2 && /docpad$/.test(process.argv[1]),
  616. welcome: process.argv.length >= 2 && /docpad$/.test(process.argv[1]),
  617. prompts: process.argv.length >= 2 && /docpad$/.test(process.argv[1])
  618. }
  619. }
  620. };
  621. DocPad.prototype.regenerateTimer = null;
  622. DocPad.prototype.getConfig = function() {
  623. return this.config || {};
  624. };
  625. DocPad.prototype.getPort = function() {
  626. var _ref1, _ref2, _ref3, _ref4;
  627. return (_ref1 = (_ref2 = (_ref3 = (_ref4 = this.getConfig().port) != null ? _ref4 : process.env.PORT) != null ? _ref3 : process.env.VCAP_APP_PORT) != null ? _ref2 : process.env.VMC_APP_PORT) != null ? _ref1 : 9778;
  628. };
  629. function DocPad(instanceConfig, next) {
  630. this.server = __bind(this.server, this);
  631. this.serverMiddleware500 = __bind(this.serverMiddleware500, this);
  632. this.serverMiddleware404 = __bind(this.serverMiddleware404, this);
  633. this.serverMiddlewareRouter = __bind(this.serverMiddlewareRouter, this);
  634. this.serveDocument = __bind(this.serveDocument, this);
  635. this.skeleton = __bind(this.skeleton, this);
  636. this.run = __bind(this.run, this);
  637. this.watch = __bind(this.watch, this);
  638. this.render = __bind(this.render, this);
  639. this.generate = __bind(this.generate, this);
  640. this.generatePostpare = __bind(this.generatePostpare, this);
  641. this.generateRender = __bind(this.generateRender, this);
  642. this.generateParse = __bind(this.generateParse, this);
  643. this.generatePrepare = __bind(this.generatePrepare, this);
  644. this.action = __bind(this.action, this);
  645. this.ensureFileOrDocument = __bind(this.ensureFileOrDocument, this);
  646. this.ensureDocument = __bind(this.ensureDocument, this);
  647. this.ensureFile = __bind(this.ensureFile, this);
  648. this.createDocument = __bind(this.createDocument, this);
  649. this.createFile = __bind(this.createFile, this);
  650. this.notify = __bind(this.notify, this);
  651. this.warn = __bind(this.warn, this);
  652. this.error = __bind(this.error, this);
  653. this.log = __bind(this.log, this);
  654. this.fatal = __bind(this.fatal, this);
  655. this.clean = __bind(this.clean, this);
  656. this.install = __bind(this.install, this);
  657. this.load = __bind(this.load, this);
  658. this.setConfig = __bind(this.setConfig, this);
  659. this.ready = __bind(this.ready, this);
  660. var action, configEventContext, console, docpad, logger, loggers, _ref1,
  661. _this = this;
  662. _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1];
  663. docpad = this;
  664. this.setMaxListeners(0);
  665. configEventContext = {
  666. docpad: docpad
  667. };
  668. this.getEvents().forEach(function(eventName) {
  669. return docpad.on(eventName, function(opts, next) {
  670. var args, eventHandler, _ref2;
  671. eventHandler = (_ref2 = docpad.getConfig().events) != null ? _ref2[eventName] : void 0;
  672. if (typeChecker.isFunction(eventHandler)) {
  673. args = [opts, next];
  674. return ambi.apply(null, [eventHandler.bind(configEventContext)].concat(__slice.call(args)));
  675. } else {
  676. return next();
  677. }
  678. });
  679. });
  680. this.actionRunnerInstance = new TaskGroup().run().on('complete', function(err) {
  681. if (err) {
  682. return docpad.error(err);
  683. }
  684. });
  685. this.errorRunnerInstance = new TaskGroup().run().on('complete', function(err) {
  686. var locale;
  687. if (err && docpad.getDebugging()) {
  688. locale = docpad.getLocale();
  689. return docpad.log('warn', locale.reportError + '\n' + locale.errorFollows, err);
  690. }
  691. });
  692. this.trackRunnerInstance = new TaskGroup().run().on('complete', function(err) {
  693. var locale;
  694. if (err && docpad.getDebugging()) {
  695. locale = docpad.getLocale();
  696. return docpad.log('warn', locale.trackError + '\n' + locale.errorFollows, err);
  697. }
  698. });
  699. if ((loggers = instanceConfig.loggers)) {
  700. delete instanceConfig.loggers;
  701. } else {
  702. logger = new (require('caterpillar').Logger)();
  703. (console = logger.pipe(new (require('caterpillar-filter').Filter)).pipe(new (require('caterpillar-human').Human))).pipe(process.stdout);
  704. loggers = {
  705. logger: logger,
  706. console: console
  707. };
  708. }
  709. safefs.unlink(this.debugLogPath, function() {});
  710. this.setLoggers(loggers);
  711. this.setLogLevel(6);
  712. this.on('log', function() {
  713. var args;
  714. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  715. return docpad.log.apply(this, args);
  716. });
  717. if (canihaz == null) {
  718. canihaz = require('canihaz')({
  719. installation: docpad.corePath,
  720. location: docpad.packagePath,
  721. key: 'lazyDependencies'
  722. });
  723. }
  724. this.slowPlugins = {};
  725. this.loadedPlugins = {};
  726. this.exchange = {};
  727. this.pluginsTemplateData = {};
  728. this.instanceConfig = {};
  729. this.collections = {};
  730. this.blocks = {};
  731. this.filesByUrl = {};
  732. this.filesBySelector = {};
  733. this.filesByOutPath = {};
  734. this.database = new FilesCollection().on('remove', function(model, options) {
  735. var outPath, url, _i, _len, _ref2;
  736. if (model.get('write') === false) {
  737. return;
  738. }
  739. _ref2 = model.get('urls') || [];
  740. for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
  741. url = _ref2[_i];
  742. delete docpad.filesByUrl[url];
  743. }
  744. outPath = model.get('outPath');
  745. if (outPath) {
  746. return _this.database.findAll({
  747. outPath: outPath
  748. }).each(function(model) {
  749. return model.set({
  750. 'mtime': new Date()
  751. });
  752. });
  753. }
  754. }).on('change:urls', function(model, urls, options) {
  755. var url, _i, _j, _len, _len1, _ref2, _results;
  756. if (urls == null) {
  757. urls = [];
  758. }
  759. if (model.get('write') === false) {
  760. return;
  761. }
  762. _ref2 = model.previous('urls') || [];
  763. for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
  764. url = _ref2[_i];
  765. delete docpad.filesByUrl[url];
  766. }
  767. _results = [];
  768. for (_j = 0, _len1 = urls.length; _j < _len1; _j++) {
  769. url = urls[_j];
  770. _results.push(docpad.filesByUrl[url] = model.cid);
  771. }
  772. return _results;
  773. }).on('change:outPath', function(model, outPath, options) {
  774. var existingModel, existingModelId, existingModelPath, message, modelPath, previousModelId, previousModels, previousOutPath, _base, _ref2;
  775. if (model.get('write') === false) {
  776. return;
  777. }
  778. previousOutPath = model.previous('outPath');
  779. if (previousOutPath) {
  780. previousModels = _this.database.findAll({
  781. outPath: previousOutPath
  782. });
  783. previousModels.each(function(model) {
  784. return model.set({
  785. 'mtime': new Date()
  786. });
  787. });
  788. previousModelId = _this.filesByOutPath[previousOutPath];
  789. if (previousModelId === model.id) {
  790. if (previousModels.length) {
  791. _this.filesByOutPath[previousOutPath] = previousModelId;
  792. } else {
  793. delete _this.filesByOutPath[previousOutPath];
  794. }
  795. }
  796. }
  797. existingModelId = (_ref2 = (_base = _this.filesByOutPath)[outPath]) != null ? _ref2 : _base[outPath] = model.id;
  798. if (existingModelId !== model.id) {
  799. modelPath = model.get('fullPath');
  800. existingModel = _this.database.get(existingModelId);
  801. existingModelPath = existingModel.get('fullPath');
  802. message = util.format(docpad.getLocale().outPathConflict, outPath, modelPath, existingModelPath);
  803. return docpad.warn(message);
  804. }
  805. });
  806. this.locales = extendr.dereference(this.locales);
  807. this.userConfig = extendr.dereference(this.userConfig);
  808. this.initialConfig = extendr.dereference(this.initialConfig);
  809. if (instanceConfig.action != null) {
  810. action = instanceConfig.action;
  811. } else {
  812. action = 'load ready';
  813. }
  814. if (action) {
  815. this.action(action, instanceConfig, function(err) {
  816. if (err) {
  817. return docpad.fatal(err);
  818. }
  819. return typeof next === "function" ? next(null, docpad) : void 0;
  820. });
  821. } else {
  822. if (typeof next === "function") {
  823. next(null, docpad);
  824. }
  825. }
  826. this;
  827. }
  828. DocPad.prototype.isIgnoredPath = function(path, opts) {
  829. if (opts == null) {
  830. opts = {};
  831. }
  832. opts = extendr.extend({
  833. ignorePaths: this.config.ignorePaths,
  834. ignoreHiddenFiles: this.config.ignoreHiddenFiles,
  835. ignoreCommonPatterns: this.config.ignoreCommonPatterns,
  836. ignoreCustomPatterns: this.config.ignoreCustomPatterns
  837. }, opts);
  838. return balUtil.isIgnoredPath(path, opts);
  839. };
  840. DocPad.prototype.scandir = function(opts) {
  841. if (opts == null) {
  842. opts = {};
  843. }
  844. opts = extendr.extend({
  845. ignorePaths: this.config.ignorePaths,
  846. ignoreHiddenFiles: this.config.ignoreHiddenFiles,
  847. ignoreCommonPatterns: this.config.ignoreCommonPatterns,
  848. ignoreCustomPatterns: this.config.ignoreCustomPatterns
  849. }, opts);
  850. return balUtil.scandir(opts);
  851. };
  852. DocPad.prototype.watchdir = function(opts) {
  853. if (opts == null) {
  854. opts = {};
  855. }
  856. opts = extendr.extend({
  857. ignorePaths: this.config.ignorePaths,
  858. ignoreHiddenFiles: this.config.ignoreHiddenFiles,
  859. ignoreCommonPatterns: this.config.ignoreCommonPatterns,
  860. ignoreCustomPatterns: this.config.ignoreCustomPatterns
  861. }, opts, this.config.watchOptions);
  862. return require('watchr').watch(opts);
  863. };
  864. DocPad.prototype.ready = function(opts, next) {
  865. var config, docpad, instanceConfig, locale, mixpanelInstance, pluginName, pluginsList, tasks, _ref1,
  866. _this = this;
  867. _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1];
  868. docpad = this;
  869. config = this.getConfig();
  870. locale = this.getLocale();
  871. mixpanelInstance = this.getMixpanelInstance();
  872. this.DocumentModel.prototype.defaults.renderSingleExtensions = config.renderSingleExtensions;
  873. this.compareVersion();
  874. if (this.getDebugging()) {
  875. pluginsList = ((function() {
  876. var _i, _len, _ref2, _results;
  877. _ref2 = Object.keys(this.loadedPlugins).sort();
  878. _results = [];
  879. for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
  880. pluginName = _ref2[_i];
  881. _results.push("" + pluginName + " v" + this.loadedPlugins[pluginName].version);
  882. }
  883. return _results;
  884. }).call(this)).join(', ');
  885. } else {
  886. pluginsList = Object.keys(this.loadedPlugins).sort().join(', ');
  887. }
  888. this.log('info', util.format(locale.welcome, "v" + (this.getVersion())));
  889. this.log('info', util.format(locale.welcomePlugins, pluginsList));
  890. this.log('info', util.format(locale.welcomeEnvironment, this.getEnvironment()));
  891. tasks = new TaskGroup().once('complete', function(err) {
  892. if (err) {
  893. return docpad.error(err);
  894. }
  895. return typeof next === "function" ? next(null, docpad) : void 0;
  896. });
  897. tasks.addTask(function(complete) {
  898. if (!config.welcome) {
  899. return complete();
  900. }
  901. return _this.emitSync('welcome', {
  902. docpad: docpad
  903. }, complete);
  904. });
  905. tasks.addTask(function(complete) {
  906. if (!mixpanelInstance || _this.userConfig.username) {
  907. return complete();
  908. }
  909. return require('getmac').getMac(function(err, macAddress) {
  910. var macAddressHash, _base, _base1, _ref2, _ref3;
  911. if (err || !macAddress) {
  912. return complete();
  913. }
  914. try {
  915. macAddressHash = require('crypto').createHmac('sha1', config.hashKey).update(macAddress).digest('hex');
  916. } catch (_error) {
  917. err = _error;
  918. if (err) {
  919. return complete();
  920. }
  921. }
  922. if (macAddressHash) {
  923. if ((_ref2 = (_base = _this.userConfig).name) == null) {
  924. _base.name = "MAC " + macAddressHash;
  925. }
  926. if ((_ref3 = (_base1 = _this.userConfig).username) == null) {
  927. _base1.username = macAddressHash;
  928. }
  929. }
  930. return complete();
  931. });
  932. });
  933. tasks.addTask(function() {
  934. var lastLogin, userData;
  935. if (!mixpanelInstance || !_this.userConfig.username) {
  936. return;
  937. }
  938. lastLogin = new Date();
  939. userData = {
  940. $email: _this.userConfig.email,
  941. $name: _this.userConfig.name,
  942. $last_login: lastLogin,
  943. $country_code: balUtil.getCountryCode(),
  944. languageCode: balUtil.getLanguageCode(),
  945. version: _this.getVersion(),
  946. platform: _this.getProcessPlatform(),
  947. nodeVersion: _this.getProcessVersion()
  948. };
  949. if (_this.userConfig.identified !== true) {
  950. mixpanelInstance.people.set(_this.userConfig.username, extendr.extend(userData, {
  951. $created: lastLogin,
  952. $username: _this.userConfig.username
  953. }));
  954. return _this.updateUserConfig({
  955. identified: true
  956. });
  957. } else {
  958. return mixpanelInstance.people.set(_this.userConfig.username, userData);
  959. }
  960. });
  961. tasks.addTask(function(complete) {
  962. return _this.emitSync('docpadReady', {
  963. docpad: docpad
  964. }, complete);
  965. });
  966. tasks.run();
  967. return this;
  968. };
  969. DocPad.prototype.mergeConfigurations = function(configPackages, configsToMerge) {
  970. var configPackage, env, envConfig, envs, _i, _j, _len, _len1, _ref1;
  971. envs = this.getEnvironments();
  972. for (_i = 0, _len = configPackages.length; _i < _len; _i++) {
  973. configPackage = configPackages[_i];
  974. if (!configPackage) {
  975. continue;
  976. }
  977. configsToMerge.push(configPackage);
  978. for (_j = 0, _len1 = envs.length; _j < _len1; _j++) {
  979. env = envs[_j];
  980. envConfig = (_ref1 = configPackage.environments) != null ? _ref1[env] : void 0;
  981. if (envConfig) {
  982. configsToMerge.push(envConfig);
  983. }
  984. }
  985. }
  986. extendr.safeDeepExtendPlainObjects.apply(extendr, configsToMerge);
  987. return this;
  988. };
  989. DocPad.prototype.setInstanceConfig = function(instanceConfig) {
  990. if (instanceConfig) {
  991. extendr.safeDeepExtendPlainObjects(this.instanceConfig, instanceConfig);
  992. if (this.config) {
  993. extendr.safeDeepExtendPlainObjects(this.config, instanceConfig);
  994. }
  995. }
  996. return this;
  997. };
  998. DocPad.prototype.setConfig = function(instanceConfig, next) {
  999. var configPackages, configsToMerge, docpad, key, postTasks, type, typePath, typePaths, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3,
  1000. _this = this;
  1001. _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1];
  1002. docpad = this;
  1003. if (instanceConfig) {
  1004. this.setInstanceConfig(instanceConfig);
  1005. }
  1006. this.config.env = this.instanceConfig.env || this.websiteConfig.env || this.initialConfig.env || process.env.NODE_ENV;
  1007. configPackages = [this.initialConfig, this.userConfig, this.websiteConfig, this.instanceConfig];
  1008. configsToMerge = [this.config];
  1009. docpad.mergeConfigurations(configPackages, configsToMerge);
  1010. if (this.config.server) {
  1011. this.setServer(this.config.server);
  1012. }
  1013. this.setLogLevel(this.config.logLevel);
  1014. this.config.rootPath = pathUtil.resolve(this.config.rootPath);
  1015. this.config.outPath = pathUtil.resolve(this.config.rootPath, this.config.outPath);
  1016. this.config.srcPath = pathUtil.resolve(this.config.rootPath, this.config.srcPath);
  1017. _ref2 = ['documents', 'files', 'layouts'];
  1018. for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
  1019. type = _ref2[_i];
  1020. typePaths = this.config[type + 'Paths'];
  1021. for (key = _j = 0, _len1 = typePaths.length; _j < _len1; key = ++_j) {
  1022. typePath = typePaths[key];
  1023. typePaths[key] = pathUtil.resolve(this.config.srcPath, typePath);
  1024. }
  1025. }
  1026. _ref3 = ['plugins'];
  1027. for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
  1028. type = _ref3[_k];
  1029. typePaths = this.config[type + 'Paths'];
  1030. for (key = _l = 0, _len3 = typePaths.length; _l < _len3; key = ++_l) {
  1031. typePath = typePaths[key];
  1032. typePaths[key] = pathUtil.resolve(this.config.rootPath, typePath);
  1033. }
  1034. }
  1035. process.removeListener('uncaughtException', this.error);
  1036. if (this.config.catchExceptions) {
  1037. process.setMaxListeners(0);
  1038. process.on('uncaughtException', this.error);
  1039. }
  1040. if (this.regenerateTimer) {
  1041. clearInterval(this.regenerateTimer);
  1042. this.regenerateTimer = null;
  1043. }
  1044. if (this.config.regenerateEvery) {
  1045. this.regenerateTimer = setInterval(function() {
  1046. docpad.log('info', locale.renderInterval);
  1047. return docpad.action('generate');
  1048. }, this.config.regenerateEvery);
  1049. }
  1050. postTasks = new TaskGroup().once('complete', function(err) {
  1051. return next(err, _this.config);
  1052. });
  1053. postTasks.addTask(function(complete) {
  1054. if (!_this.config.detectEncoding) {
  1055. return complete();
  1056. }
  1057. return canihaz('iconv', complete);
  1058. });
  1059. postTasks.addTask(function(complete) {
  1060. return _this.loadPlugins(complete);
  1061. });
  1062. postTasks.addTask(function(complete) {
  1063. return _this.extendCollections(complete);
  1064. });
  1065. postTasks.addTask(function(complete) {
  1066. return _this.emitSync('extendTemplateData', {
  1067. templateData: _this.pluginsTemplateData
  1068. }, complete);
  1069. });
  1070. postTasks.addTask(function(complete) {
  1071. return _this.emitSync('docpadLoaded', {}, complete);
  1072. });
  1073. postTasks.run();
  1074. return this;
  1075. };
  1076. DocPad.prototype.load = function(instanceConfig, next) {
  1077. var docpad, locale, preTasks, _ref1,
  1078. _this = this;
  1079. _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1];
  1080. docpad = this;
  1081. locale = this.getLocale();
  1082. instanceConfig || (instanceConfig = {});
  1083. this.websitePackageConfig = {};
  1084. this.websiteConfig = {};
  1085. this.config = {};
  1086. this.setInstanceConfig(instanceConfig);
  1087. preTasks = new TaskGroup().once('complete', function(err) {
  1088. if (err) {
  1089. return next(err);
  1090. }
  1091. return _this.setConfig(next);
  1092. });
  1093. preTasks.addTask(function(complete) {
  1094. return balUtil.getHomePath(function(err, homePath) {
  1095. var dropboxPath;
  1096. if (err) {
  1097. return complete(err);
  1098. }
  1099. dropboxPath = pathUtil.join(homePath, 'Dropbox');
  1100. return safefs.exists(dropboxPath, function(dropboxPathExists) {
  1101. var userConfigDirPath;
  1102. userConfigDirPath = dropboxPathExists ? dropboxPath : homePath;
  1103. _this.userConfigPath = pathUtil.join(userConfigDirPath, _this.userConfigPath);
  1104. return complete();
  1105. });
  1106. });
  1107. });
  1108. preTasks.addTask(function(complete) {
  1109. return _this.loadConfigPath(_this.userConfigPath, function(err, data) {
  1110. if (err) {
  1111. return complete(err);
  1112. }
  1113. extendr.extend(_this.userConfig, data || {});
  1114. return complete();
  1115. });
  1116. });
  1117. preTasks.addTask(function(complete) {
  1118. return _this.loadConfigPath(_this.packagePath, function(err, data) {
  1119. var _ref2;
  1120. if (err) {
  1121. return complete(err);
  1122. }
  1123. data || (data = {});
  1124. _this.version = data.version;
  1125. if ((_ref2 = _this.getAirbrakeInstance()) != null) {
  1126. _ref2.appVersion = data.version;
  1127. }
  1128. return complete();
  1129. });
  1130. });
  1131. preTasks.addTask(function(complete) {
  1132. var rootPath, websitePackagePath;
  1133. rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.initialConfig.rootPath);
  1134. websitePackagePath = pathUtil.resolve(rootPath, _this.instanceConfig.packagePath || _this.initialConfig.packagePath);
  1135. return _this.loadConfigPath(websitePackagePath, function(err, data) {
  1136. if (err) {
  1137. return complete(err);
  1138. }
  1139. data || (data = {});
  1140. _this.websitePackageConfig = data;
  1141. return complete();
  1142. });
  1143. });
  1144. preTasks.addTask(function(complete) {
  1145. var envPath, rootPath;
  1146. rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.websitePackageConfig.rootPath || _this.initialConfig.rootPath);
  1147. envPath = pathUtil.join(rootPath, '.env');
  1148. return safefs.exists(envPath, function(exists) {
  1149. if (!exists) {
  1150. return complete();
  1151. }
  1152. return safefs.readFile(envPath, function(err, data) {
  1153. var key, line, lines, match, result, value, _i, _len;
  1154. if (err) {
  1155. return complete(err);
  1156. }
  1157. result = data.toString();
  1158. lines = result.split('\n');
  1159. for (_i = 0, _len = lines.length; _i < _len; _i++) {
  1160. line = lines[_i];
  1161. match = line.match(/^([^=]+?)=(.*)/);
  1162. if (match) {
  1163. key = match[1];
  1164. value = match[2];
  1165. process.env[key] = value;
  1166. }
  1167. }
  1168. return complete();
  1169. });
  1170. });
  1171. });
  1172. preTasks.addTask(function(complete) {
  1173. var configPath, configPaths, index, rootPath, _i, _len;
  1174. rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.initialConfig.rootPath);
  1175. configPaths = _this.instanceConfig.configPaths || _this.initialConfig.configPaths;
  1176. for (index = _i = 0, _len = configPaths.length; _i < _len; index = ++_i) {
  1177. configPath = configPaths[index];
  1178. configPaths[index] = pathUtil.resolve(rootPath, configPath);
  1179. }
  1180. return _this.loadConfigPaths(configPaths, function(err, data) {
  1181. if (err) {
  1182. return complete(err);
  1183. }
  1184. data || (data = {});
  1185. extendr.extend(_this.websiteConfig, data);
  1186. return complete();
  1187. });
  1188. });
  1189. preTasks.run();
  1190. return this;
  1191. };
  1192. DocPad.prototype.install = function(opts, next) {
  1193. var docpad, _ref1;
  1194. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  1195. docpad = this;
  1196. this.initNodeModules({
  1197. path: this.config.rootPath,
  1198. output: true,
  1199. next: function(err) {
  1200. if (err) {
  1201. return next(err);
  1202. }
  1203. return docpad.load(function(err) {
  1204. return next(err);
  1205. });
  1206. }
  1207. });
  1208. return this;
  1209. };
  1210. DocPad.prototype.clean = function(opts, next) {
  1211. var docpad, locale, outPath, rootPath, _ref1, _ref2;
  1212. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  1213. docpad = this;
  1214. locale = this.getLocale();
  1215. _ref2 = this.config, rootPath = _ref2.rootPath, outPath = _ref2.outPath;
  1216. docpad.log('debug', locale.renderCleaning);
  1217. docpad.resetCollections(function(err) {
  1218. if (err) {
  1219. return next(err);
  1220. }
  1221. if (rootPath.indexOf(outPath) !== -1) {
  1222. return next();
  1223. } else {
  1224. return balUtil.rmdirDeep(outPath, function(err, list, tree) {
  1225. if (!err) {
  1226. docpad.log('debug', locale.renderCleaned);
  1227. }
  1228. return next();
  1229. });
  1230. }
  1231. });
  1232. return this;
  1233. };
  1234. DocPad.prototype.updateUserConfig = function(data, next) {
  1235. var docpad, userConfigPath, _ref1;
  1236. if (data == null) {
  1237. data = {};
  1238. }
  1239. _ref1 = balUtil.extractOptsAndCallback(data, next), data = _ref1[0], next = _ref1[1];
  1240. docpad = this;
  1241. userConfigPath = this.userConfigPath;
  1242. if (data) {
  1243. extendr.extend(this.userConfig, data);
  1244. }
  1245. CSON.stringify(this.userConfig, function(err, userConfigString) {
  1246. if (err) {
  1247. return typeof next === "function" ? next(err) : void 0;
  1248. }
  1249. return safefs.writeFile(userConfigPath, userConfigString, 'utf8', function(err) {
  1250. return typeof next === "function" ? next(err) : void 0;
  1251. });
  1252. });
  1253. return this;
  1254. };
  1255. DocPad.prototype.loadConfigUrl = function(configUrl, next) {
  1256. var locale;
  1257. locale = this.getLocale();
  1258. this.log('debug', util.format(locale.loadingConfigUrl, configUrl));
  1259. balUtil.readPath(configUrl, function(err, body) {
  1260. if (err) {
  1261. return next(err);
  1262. }
  1263. return CSON.parse(body, next);
  1264. });
  1265. return this;
  1266. };
  1267. DocPad.prototype.loadConfigPath = function(configPath, next) {
  1268. var locale;
  1269. locale = this.getLocale();
  1270. this.log('debug', util.format(locale.loadingConfigPath, configPath));
  1271. safefs.exists(configPath, function(exists) {
  1272. if (!exists) {
  1273. return next(null, null);
  1274. }
  1275. return CSON.parseFile(configPath, next);
  1276. });
  1277. return this;
  1278. };
  1279. DocPad.prototype.loadConfigPaths = function(configPaths, next) {
  1280. var docpad, result, tasks;
  1281. docpad = this;
  1282. result = null;
  1283. if (!typeChecker.isArray(configPaths)) {
  1284. configPaths = [configPaths];
  1285. }
  1286. tasks = new TaskGroup().once('complete', function(err) {
  1287. return next(err, result);
  1288. });
  1289. configPaths.forEach(function(configPath) {
  1290. return tasks.addTask(function(complete) {
  1291. if (result) {
  1292. return complete();
  1293. }
  1294. return docpad.loadConfigPath(configPath, function(err, config) {
  1295. if (err) {
  1296. return complete(err);
  1297. }
  1298. if (config) {
  1299. result = config;
  1300. tasks.clear();
  1301. return complete();
  1302. } else {
  1303. return complete();
  1304. }
  1305. });
  1306. });
  1307. });
  1308. tasks.run();
  1309. return this;
  1310. };
  1311. DocPad.prototype.extendCollections = function(next) {
  1312. var config, database, docpad, locale, tasks;
  1313. docpad = this;
  1314. config = this.config;
  1315. locale = this.getLocale();
  1316. database = this.getDatabase();
  1317. this.setCollections({
  1318. documents: database.createLiveChildCollection().setQuery('isDocument', {
  1319. $or: {
  1320. isDocument: true,
  1321. fullPath: {
  1322. $startsWith: config.documentsPaths
  1323. }
  1324. }
  1325. }).on('add', function(model) {
  1326. docpad.log('debug', util.format(locale.addingDocument, model.attributes.fullPath));
  1327. return model.setDefaults({
  1328. isDocument: true,
  1329. render: true,
  1330. write: true
  1331. });
  1332. }),
  1333. files: database.createLiveChildCollection().setQuery('isFile', {
  1334. $or: {
  1335. isFile: true,
  1336. fullPath: {
  1337. $startsWith: config.filesPaths
  1338. }
  1339. }
  1340. }).on('add', function(model) {
  1341. docpad.log('debug', util.format(locale.addingFile, model.attributes.fullPath));
  1342. return model.setDefaults({
  1343. isFile: true,
  1344. render: false,
  1345. write: true
  1346. });
  1347. }),
  1348. layouts: database.createLiveChildCollection().setQuery('isLayout', {
  1349. $or: {
  1350. isLayout: true,
  1351. fullPath: {
  1352. $startsWith: config.layoutsPaths
  1353. }
  1354. }
  1355. }).on('add', function(model) {
  1356. docpad.log('debug', util.format(locale.addingLayout, model.attributes.fullPath));
  1357. return model.setDefaults({
  1358. isLayout: true,
  1359. render: false,
  1360. write: false
  1361. });
  1362. }),
  1363. html: database.createLiveChildCollection().setQuery('isHTML', {
  1364. $or: {
  1365. isDocument: true,
  1366. isFile: true
  1367. },
  1368. outExtension: 'html'
  1369. }).on('add', function(model) {
  1370. return docpad.log('debug', util.format(locale.addingHtml, model.attributes.fullPath));
  1371. }),
  1372. stylesheet: database.createLiveChildCollection().setQuery('isStylesheet', {
  1373. $or: {
  1374. isDocument: true,
  1375. isFile: true
  1376. },
  1377. outExtension: {
  1378. $in: ['css', 'scss', 'sass', 'styl', 'stylus', 'less']
  1379. }
  1380. }).on('add', function(model) {
  1381. docpad.log('debug', util.format(locale.addingStylesheet, model.attributes.fullPath));
  1382. return model.setDefaults({
  1383. referencesOthers: true
  1384. });
  1385. })
  1386. });
  1387. this.setBlocks({
  1388. meta: new MetaCollection(),
  1389. scripts: new ScriptsCollection(),
  1390. styles: new StylesCollection()
  1391. });
  1392. tasks = new TaskGroup().setConfig({
  1393. concurrency: 0
  1394. }).once('complete', function(err) {
  1395. if (err) {
  1396. docpad.error(err);
  1397. }
  1398. return docpad.emitSync('extendCollections', {}, next);
  1399. });
  1400. eachr(this.config.collections || {}, function(fn, name) {
  1401. return tasks.addTask(function(complete) {
  1402. var collection;
  1403. if (fn.length === 2) {
  1404. return fn.call(docpad, database, function(err, collection) {
  1405. if (err) {
  1406. docpad.error(err);
  1407. }
  1408. if (collection) {
  1409. collection.live(true);
  1410. }
  1411. docpad.setCollection(name, collection);
  1412. return complete();
  1413. });
  1414. } else {
  1415. collection = fn.call(docpad, database);
  1416. if (collection) {
  1417. collection.live(true);
  1418. }
  1419. docpad.setCollection(name, collection);
  1420. return complete();
  1421. }
  1422. });
  1423. });
  1424. tasks.run();
  1425. return this;
  1426. };
  1427. DocPad.prototype.resetCollections = function(next) {
  1428. var database;
  1429. database = this.getDatabase();
  1430. this.databaseCache = new FilesCollection(database.models);
  1431. database.reset([]);
  1432. this.getBlock('meta').reset([]).add(["<meta http-equiv=\"X-Powered-By\" content=\"DocPad v" + docpad.version + "\"/>"]);
  1433. this.getBlock('scripts').reset([]);
  1434. this.getBlock('styles').reset([]);
  1435. this.filesByUrl = {};
  1436. this.filesBySelector = {};
  1437. this.filesByOutPath = {};
  1438. this.emitSync('populateCollections', {}, next);
  1439. return this;
  1440. };
  1441. DocPad.prototype.initGitRepo = function(opts) {
  1442. balUtil.initGitRepo(opts);
  1443. return this;
  1444. };
  1445. DocPad.prototype.initNodeModules = function(opts) {
  1446. var _ref1, _ref2;
  1447. if (opts == null) {
  1448. opts = {};
  1449. }
  1450. if ((_ref1 = opts.force) == null) {
  1451. opts.force = this.config.force;
  1452. }
  1453. if ((_ref2 = opts.output) == null) {
  1454. opts.output = this.getDebugging();
  1455. }
  1456. balUtil.initNodeModules(opts);
  1457. return this;
  1458. };
  1459. DocPad.prototype.setLogLevel = function(level) {
  1460. var loggers, _ref1;
  1461. this.getLogger().setConfig({
  1462. level: level
  1463. });
  1464. if (level === 7) {
  1465. loggers = this.getLoggers();
  1466. if ((_ref1 = loggers.debug) == null) {
  1467. loggers.debug = loggers.logger.pipe(new (require('caterpillar-human').Human)({
  1468. color: false
  1469. })).pipe(require('fs').createWriteStream(this.debugLogPath));
  1470. }
  1471. }
  1472. return this;
  1473. };
  1474. DocPad.prototype.getLogLevel = function() {
  1475. return this.config.logLevel;
  1476. };
  1477. DocPad.prototype.getDebugging = function() {
  1478. return this.getLogLevel() === 7;
  1479. };
  1480. DocPad.prototype.fatal = function(err) {
  1481. var config, docpad;
  1482. docpad = this;
  1483. config = this.getConfig();
  1484. if (!err) {
  1485. return this;
  1486. }
  1487. this.error(err, 'err', function() {
  1488. if (config.catchExceptions) {
  1489. return process.exit(-1);
  1490. } else {
  1491. throw err;
  1492. }
  1493. });
  1494. return this;
  1495. };
  1496. DocPad.prototype.log = function() {
  1497. var args, logger;
  1498. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1499. logger = this.getLogger();
  1500. logger.log.apply(logger, args);
  1501. return this;
  1502. };
  1503. DocPad.prototype.error = function(err, type, next) {
  1504. var airbrake, docpad, locale, _ref1;
  1505. if (type == null) {
  1506. type = 'err';
  1507. }
  1508. docpad = this;
  1509. locale = this.getLocale();
  1510. if (!err || err.logged) {
  1511. if (typeof next === "function") {
  1512. next();
  1513. }
  1514. return this;
  1515. }
  1516. err.logged = true;
  1517. if (err.message == null) {
  1518. err = new Error(err);
  1519. }
  1520. err.logged = true;
  1521. docpad.log(type, locale.errorOccured, '\n' + ((_ref1 = err.stack) != null ? _ref1 : err.message));
  1522. docpad.notify(err.message, {
  1523. title: locale.errorOccured
  1524. });
  1525. airbrake = this.getAirbrakeInstance();
  1526. if (airbrake) {
  1527. err.params = {
  1528. docpadVersion: this.version,
  1529. docpadConfig: this.config
  1530. };
  1531. this.getErrorRunner().addTask(function(complete) {
  1532. return airbrake.notify(err, function(airbrakeErr, airbrakeUrl) {
  1533. if (airbrakeErr) {
  1534. return complete(airbrakeErr);
  1535. } else {
  1536. console.log(util.format(locale.errorLoggedTo, airbrakeUrl));
  1537. return complete();
  1538. }
  1539. });
  1540. });
  1541. } else {
  1542. if (typeof next === "function") {
  1543. next();
  1544. }
  1545. }
  1546. return this;
  1547. };
  1548. DocPad.prototype.warn = function(message, err, next) {
  1549. var docpad, locale;
  1550. docpad = this;
  1551. locale = this.getLocale();
  1552. docpad.log('warn', message);
  1553. if (err) {
  1554. docpad.error(err, 'warn', next);
  1555. }
  1556. docpad.notify(message, {
  1557. title: locale.warnOccured
  1558. });
  1559. return this;
  1560. };
  1561. DocPad.prototype.notify = function(message, opts) {
  1562. var docpad, err, growl;
  1563. docpad = this;
  1564. growl = this.getGrowlInstance();
  1565. if (growl) {
  1566. try {
  1567. growl(message, opts);
  1568. } catch (_error) {
  1569. err = _error;
  1570. }
  1571. }
  1572. return this;
  1573. };
  1574. DocPad.prototype.track = function(name, data, next) {
  1575. var mixpanelInstance, _ref1, _ref2;
  1576. if (data == null) {
  1577. data = {};
  1578. }
  1579. mixpanelInstance = this.getMixpanelInstance();
  1580. if (mixpanelInstance) {
  1581. if ((_ref1 = this.userConfig) != null ? _ref1.username : void 0) {
  1582. data.distinct_id = this.userConfig.username;
  1583. data.username = this.userConfig.username;
  1584. }
  1585. if ((_ref2 = this.websitePackageConfig) != null ? _ref2.name : void 0) {
  1586. data.websiteName = this.websitePackageConfig.name;
  1587. }
  1588. data.version = this.getVersion();
  1589. data.platform = this.getProcessPlatform();
  1590. data.nodeVersion = this.getProcessVersion();
  1591. data.environment = this.getEnvironment();
  1592. eachr(this.loadedPlugins, function(value, key) {
  1593. return data['plugin-' + key] = value.version || true;
  1594. });
  1595. this.getTrackRunner().addTask(function(complete) {
  1596. return mixpanelInstance.track(name, data, function(err) {
  1597. if (typeof next === "function") {
  1598. next();
  1599. }
  1600. return complete(err);
  1601. });
  1602. });
  1603. }
  1604. return this;
  1605. };
  1606. DocPad.prototype.createFile = function(data, options) {
  1607. var docpad, file;
  1608. if (data == null) {
  1609. data = {};
  1610. }
  1611. if (options == null) {
  1612. options = {};
  1613. }
  1614. docpad = this;
  1615. options = extendr.extend({
  1616. detectEncoding: this.config.detectEncoding,
  1617. outDirPath: this.config.outPath
  1618. }, options);
  1619. file = new FileModel(data, options);
  1620. file.on('log', function() {
  1621. var args;
  1622. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1623. return docpad.log.apply(docpad, args);
  1624. });
  1625. file.on('render', function() {
  1626. var args;
  1627. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1628. return docpad.emitSync.apply(docpad, ['render'].concat(__slice.call(args)));
  1629. });
  1630. return file;
  1631. };
  1632. DocPad.prototype.createDocument = function(data, options) {
  1633. var docpad, document;
  1634. if (data == null) {
  1635. data = {};
  1636. }
  1637. if (options == null) {
  1638. options = {};
  1639. }
  1640. docpad = this;
  1641. options = extendr.extend({
  1642. detectEncoding: this.config.detectEncoding,
  1643. outDirPath: this.config.outPath
  1644. }, options);
  1645. document = new DocumentModel(data, options);
  1646. document.on('log', function() {
  1647. var args;
  1648. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1649. return docpad.log.apply(docpad, args);
  1650. });
  1651. document.on('getLayout', function(opts, next) {
  1652. var layout;
  1653. if (opts == null) {
  1654. opts = {};
  1655. }
  1656. opts.collection = docpad.getCollection('layouts');
  1657. layout = docpad.getFileBySelector(opts.selector, opts);
  1658. return next(null, {
  1659. layout: layout
  1660. });
  1661. });
  1662. document.on('render', function() {
  1663. var args;
  1664. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1665. return docpad.emitSync.apply(docpad, ['render'].concat(__slice.call(args)));
  1666. });
  1667. document.on('renderDocument', function() {
  1668. var args;
  1669. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1670. return docpad.emitSync.apply(docpad, ['renderDocument'].concat(__slice.call(args)));
  1671. });
  1672. return document;
  1673. };
  1674. DocPad.prototype.ensureFile = function(data, options) {
  1675. var database, result;
  1676. if (data == null) {
  1677. data = {};
  1678. }
  1679. if (options == null) {
  1680. options = {};
  1681. }
  1682. database = this.getDatabase();
  1683. result = database.findOne({
  1684. fullPath: data.fullPath
  1685. });
  1686. if (!result) {
  1687. result = this.createFile(data, options);
  1688. database.add(result);
  1689. }
  1690. return result;
  1691. };
  1692. DocPad.prototype.ensureDocument = function(data, options) {
  1693. var database, result;
  1694. if (data == null) {
  1695. data = {};
  1696. }
  1697. if (options == null) {
  1698. options = {};
  1699. }
  1700. database = this.getDatabase();
  1701. result = database.findOne({
  1702. fullPath: data.fullPath
  1703. });
  1704. if (!result) {
  1705. result = this.createDocument(data, options);
  1706. database.add(result);
  1707. }
  1708. return result;
  1709. };
  1710. DocPad.prototype.ensureFileOrDocument = function(data, options) {
  1711. var config, database, dirPath, docpad, fileFullPath, result, _i, _j, _len, _len1, _ref1, _ref2;
  1712. if (data == null) {
  1713. data = {};
  1714. }
  1715. if (options == null) {
  1716. options = {};
  1717. }
  1718. docpad = this;
  1719. config = this.getConfig();
  1720. database = this.getDatabase();
  1721. fileFullPath = data.fullPath || null;
  1722. result = database.findOne({
  1723. fullPath: fileFullPath
  1724. });
  1725. if (!result) {
  1726. if (fileFullPath) {
  1727. _ref1 = config.documentsPaths.concat(config.layoutsPaths);
  1728. for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
  1729. dirPath = _ref1[_i];
  1730. if (fileFullPath.indexOf(dirPath) === 0) {
  1731. data.relativePath || (data.relativePath = fileFullPath.replace(dirPath, '').replace(/^[\/\\]/, ''));
  1732. result = this.createDocument(data, options);
  1733. break;
  1734. }
  1735. }
  1736. if (!result) {
  1737. _ref2 = config.filesPaths;
  1738. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  1739. dirPath = _ref2[_j];
  1740. if (fileFullPath.indexOf(dirPath) === 0) {
  1741. data.relativePath || (data.relativePath = fileFullPath.replace(dirPath, '').replace(/^[\/\\]/, ''));
  1742. result = this.createFile(data, options);
  1743. break;
  1744. }
  1745. }
  1746. }
  1747. }
  1748. if (!result) {
  1749. result = this.createDocument(data, options);
  1750. }
  1751. database.add(result);
  1752. }
  1753. return result;
  1754. };
  1755. DocPad.prototype.parseFileDirectory = function(opts, next) {
  1756. var _ref1;
  1757. if (opts == null) {
  1758. opts = {};
  1759. }
  1760. if ((_ref1 = opts.createFunction) == null) {
  1761. opts.createFunction = this.createFile;
  1762. }
  1763. return this.parseDirectory(opts, next);
  1764. };
  1765. DocPad.prototype.parseDocumentDirectory = function(opts, next) {
  1766. var _ref1;
  1767. if (opts == null) {
  1768. opts = {};
  1769. }
  1770. if ((_ref1 = opts.createFunction) == null) {
  1771. opts.createFunction = this.createDocument;
  1772. }
  1773. return this.parseDirectory(opts, next);
  1774. };
  1775. DocPad.prototype.parseDirectory = function(opts, next) {
  1776. var createFunction, docpad, filesToLoad, locale, path;
  1777. if (opts == null) {
  1778. opts = {};
  1779. }
  1780. docpad = this;
  1781. locale = this.getLocale();
  1782. path = opts.path, createFunction = opts.createFunction;
  1783. filesToLoad = new FilesCollection();
  1784. if (!safefs.existsSync(path)) {
  1785. docpad.log('debug', util.format(locale.renderDirectoryNonexistant, path));
  1786. return next();
  1787. }
  1788. docpad.log('debug', util.format(locale.renderDirectoryParsing, path));
  1789. this.scandir({
  1790. path: path,
  1791. fileAction: function(fileFullPath, fileRelativePath, nextFile, fileStat) {
  1792. var data, file, options;
  1793. data = {
  1794. fullPath: fileFullPath,
  1795. relativePath: fileRelativePath
  1796. };
  1797. options = {
  1798. stat: fileStat
  1799. };
  1800. file = createFunction(data, options);
  1801. filesToLoad.add(file);
  1802. return nextFile();
  1803. },
  1804. next: function(err) {
  1805. if (err) {
  1806. return next(err);
  1807. }
  1808. docpad.log('debug', util.format(locale.renderDirectoryParsed, path));
  1809. return docpad.loadFiles({
  1810. collection: filesToLoad
  1811. }, function(err) {
  1812. return next(err);
  1813. });
  1814. }
  1815. });
  1816. return this;
  1817. };
  1818. DocPad.prototype.getPlugin = function(pluginName) {
  1819. return this.loadedPlugins[pluginName];
  1820. };
  1821. DocPad.prototype.hasPlugins = function() {
  1822. return typeChecker.isEmptyObject(this.loadedPlugins) === false;
  1823. };
  1824. DocPad.prototype.loadPlugins = function(next) {
  1825. var docpad, locale, snore, tasks,
  1826. _this = this;
  1827. docpad = this;
  1828. locale = this.getLocale();
  1829. this.slowPlugins = {};
  1830. snore = balUtil.createSnore(function() {
  1831. return docpad.log('notice', util.format(locale.pluginsSlow, Object.keys(docpad.slowPlugins).join(', ')));
  1832. });
  1833. tasks = new TaskGroup().setConfig({
  1834. concurrency: 0
  1835. }).once('complete', function(err) {
  1836. docpad.slowPlugins = {};
  1837. snore.clear();
  1838. return next(err);
  1839. });
  1840. (this.config.pluginsPaths || []).forEach(function(pluginsPath) {
  1841. var exists;
  1842. exists = safefs.existsSync(pluginsPath);
  1843. if (exists) {
  1844. return tasks.addTask(function(complete) {
  1845. return _this.loadPluginsIn(pluginsPath, complete);
  1846. });
  1847. }
  1848. });
  1849. (this.config.pluginPaths || []).forEach(function(pluginPath) {
  1850. var exists;
  1851. exists = safefs.existsSync(pluginPath);
  1852. if (exists) {
  1853. return tasks.addTask(function(complete) {
  1854. return _this.loadPlugin(pluginPath, complete);
  1855. });
  1856. }
  1857. });
  1858. tasks.run();
  1859. return this;
  1860. };
  1861. DocPad.prototype.loadedPlugin = function(pluginName, next) {
  1862. var docpad, loaded;
  1863. docpad = this;
  1864. loaded = docpad.loadedPlugins[pluginName] != null;
  1865. next(null, loaded);
  1866. return this;
  1867. };
  1868. DocPad.prototype.loadPlugin = function(fileFullPath, _next) {
  1869. var config, docpad, enabled, loader, locale, next, pluginName;
  1870. docpad = this;
  1871. config = this.getConfig();
  1872. locale = this.getLocale();
  1873. next = function(err) {
  1874. delete docpad.slowPlugins[pluginName];
  1875. return _next(err);
  1876. };
  1877. loader = new PluginLoader({
  1878. dirPath: fileFullPath,
  1879. docpad: this,
  1880. BasePlugin: BasePlugin
  1881. });
  1882. pluginName = loader.pluginName;
  1883. enabled = (config.enableUnlistedPlugins && (config.enabledPlugins[pluginName] != null) === false) || config.enabledPlugins[pluginName] === true;
  1884. if (docpad.loadedPlugins[pluginName] != null) {
  1885. docpad.loadedPlugins[pluginName].setConfig();
  1886. return _next();
  1887. }
  1888. docpad.slowPlugins[pluginName] = true;
  1889. if (!enabled) {
  1890. docpad.log('debug', util.format(locale.pluginSkipped, pluginName));
  1891. return next();
  1892. } else {
  1893. docpad.log('debug', util.format(locale.pluginLoading, pluginName));
  1894. loader.exists(function(err, exists) {
  1895. if (err || !exists) {
  1896. return next(err);
  1897. }
  1898. return loader.unsupported(function(err, unsupported) {
  1899. if (err) {
  1900. return next(err);
  1901. }
  1902. if (unsupported) {
  1903. if (unsupported === 'version' && config.skipUnsupportedPlugins === false) {
  1904. docpad.log('warn', util.format(locale.pluginContinued, pluginName));
  1905. } else {
  1906. if (unsupported === 'type') {
  1907. docpad.log('debug', util.format(locale.pluginSkippedDueTo, pluginName, unsupported));
  1908. } else {
  1909. docpad.log('warn', util.format(locale.pluginSkippedDueTo, pluginName, unsupported));
  1910. }
  1911. return next();
  1912. }
  1913. }
  1914. return loader.load(function(err) {
  1915. if (err) {
  1916. return next(err);
  1917. }
  1918. return loader.create({}, function(err, pluginInstance) {
  1919. if (err) {
  1920. return next(err);
  1921. }
  1922. docpad.loadedPlugins[loader.pluginName] = pluginInstance;
  1923. docpad.log('debug', util.format(locale.pluginLoaded, pluginName));
  1924. return next();
  1925. });
  1926. });
  1927. });
  1928. });
  1929. }
  1930. return this;
  1931. };
  1932. DocPad.prototype.loadPluginsIn = function(pluginsPath, next) {
  1933. var docpad, locale;
  1934. docpad = this;
  1935. locale = this.getLocale();
  1936. docpad.log('debug', util.format(locale.pluginsLoadingFor, pluginsPath));
  1937. this.scandir({
  1938. path: pluginsPath,
  1939. fileAction: false,
  1940. dirAction: function(fileFullPath, fileRelativePath, _nextFile) {
  1941. var nextFile, pluginName;
  1942. pluginName = pathUtil.basename(fileFullPath);
  1943. if (fileFullPath === pluginsPath) {
  1944. return _nextFile(null, false);
  1945. }
  1946. nextFile = function(err, skip) {
  1947. if (err) {
  1948. docpad.warn(util.format(locale.pluginFailedToLoad, pluginName, fileFullPath) + '\n' + locale.errorFollows, err);
  1949. }
  1950. return _nextFile(null, skip);
  1951. };
  1952. return docpad.loadPlugin(fileFullPath, function(err) {
  1953. return nextFile(err, true);
  1954. });
  1955. },
  1956. next: function(err) {
  1957. docpad.log('debug', util.format(locale.pluginsLoadedFor, pluginsPath));
  1958. return next(err);
  1959. }
  1960. });
  1961. return this;
  1962. };
  1963. DocPad.prototype.compareVersion = function() {
  1964. var docpad, locale;
  1965. if (!this.config.checkVersion) {
  1966. return this;
  1967. }
  1968. docpad = this;
  1969. locale = this.getLocale();
  1970. balUtil.packageCompare({
  1971. local: this.packagePath,
  1972. remote: this.config.latestPackageUrl,
  1973. newVersionCallback: function(details) {
  1974. docpad.notify(locale.upgradeNotification);
  1975. return docpad.log('notice', util.format(locale.upgradeDetails, details.local.version, details.remote.version, details.local.upgradeUrl || details.remote.installUrl || details.remote.homepage));
  1976. }
  1977. });
  1978. return this;
  1979. };
  1980. DocPad.prototype.getExchange = function(next) {
  1981. var exchangeUrl;
  1982. if (!typeChecker.isEmptyObject(this.exchange)) {
  1983. return next(null, this.exchange);
  1984. }
  1985. exchangeUrl = this.config.exchangeUrl + '?version=' + this.version;
  1986. this.loadConfigUrl(exchangeUrl, function(err, parsedData) {
  1987. if (err) {
  1988. return next(err);
  1989. }
  1990. this.exchange = parsedData;
  1991. return next(null, parsedData);
  1992. });
  1993. return this;
  1994. };
  1995. DocPad.prototype.installSkeleton = function(skeletonModel, destinationPath, next) {
  1996. var docpad, packagePath, repoConfig;
  1997. docpad = this;
  1998. packagePath = pathUtil.join(destinationPath, 'package.json');
  1999. repoConfig = {
  2000. path: destinationPath,
  2001. url: skeletonModel.get('repo'),
  2002. branch: skeletonModel.get('branch'),
  2003. remote: 'skeleton',
  2004. output: true,
  2005. next: function(err) {
  2006. if (err) {
  2007. return docpad.error(err);
  2008. }
  2009. return docpad.initNodeModules({
  2010. path: destinationPath,
  2011. output: true,
  2012. next: function(err) {
  2013. if (err) {
  2014. return docpad.error(err);
  2015. }
  2016. return next();
  2017. }
  2018. });
  2019. }
  2020. };
  2021. safefs.ensurePath(destinationPath, function(err) {
  2022. if (err) {
  2023. return docpad.error(err);
  2024. }
  2025. return docpad.initGitRepo(repoConfig);
  2026. });
  2027. return this;
  2028. };
  2029. DocPad.prototype.loadFiles = function(opts, next) {
  2030. var collection, database, docpad, locale, tasks;
  2031. if (opts == null) {
  2032. opts = {};
  2033. }
  2034. docpad = this;
  2035. locale = this.getLocale();
  2036. database = this.getDatabase();
  2037. collection = opts.collection;
  2038. docpad.log('debug', util.format(locale.loadingFiles, collection.length));
  2039. tasks = new TaskGroup().setConfig({
  2040. concurrency: 0
  2041. }).once('complete', function(err) {
  2042. if (err) {
  2043. return next(err);
  2044. }
  2045. return docpad.emitSync('loadAfter', {
  2046. collection: collection
  2047. }, function(err) {
  2048. docpad.log('debug', util.format(locale.loadedFiles, collection.length));
  2049. return next();
  2050. });
  2051. });
  2052. collection.forEach(function(file) {
  2053. return tasks.addTask(function(complete) {
  2054. var fileRelativePath;
  2055. fileRelativePath = file.get('relativePath');
  2056. docpad.log('debug', util.format(locale.loadingFile, fileRelativePath));
  2057. return file.load(function(err) {
  2058. var fileIgnored, fileParse;
  2059. if (err) {
  2060. docpad.warn(util.format(locale.loadingFileFailed, fileRelativePath) + "\n" + locale.errorFollows, err);
  2061. return complete();
  2062. }
  2063. fileIgnored = file.get('ignored');
  2064. fileParse = file.get('parse');
  2065. if (fileIgnored || ((fileParse != null) && !fileParse)) {
  2066. docpad.log('info', util.format(locale.loadingFileIgnored, fileRelativePath));
  2067. collection.remove(file);
  2068. return complete();
  2069. } else {
  2070. docpad.log('debug', util.format(locale.loadedFile, fileRelativePath));
  2071. }
  2072. database.add(file);
  2073. return complete();
  2074. });
  2075. });
  2076. });
  2077. docpad.emitSync('loadBefore', {
  2078. collection: collection
  2079. }, function(err) {
  2080. if (err) {
  2081. return next(err);
  2082. }
  2083. return tasks.run();
  2084. });
  2085. return this;
  2086. };
  2087. DocPad.prototype.contextualizeFiles = function(opts, next) {
  2088. var collection, docpad, locale, tasks, templateData, _ref1;
  2089. if (opts == null) {
  2090. opts = {};
  2091. }
  2092. docpad = this;
  2093. locale = this.getLocale();
  2094. collection = opts.collection, templateData = opts.templateData;
  2095. docpad.log('debug', util.format(locale.contextualizingFiles, collection.length));
  2096. tasks = new TaskGroup().setConfig({
  2097. concurrency: 0
  2098. }).once('complete', function(err) {
  2099. if (err) {
  2100. return next(err);
  2101. }
  2102. return docpad.emitSync('contextualizeAfter', {
  2103. collection: collection
  2104. }, function(err) {
  2105. if (err) {
  2106. return next(err);
  2107. }
  2108. docpad.log('debug', util.format(locale.contextualizedFiles, collection.length));
  2109. return next();
  2110. });
  2111. });
  2112. if ((_ref1 = opts.progress) != null) {
  2113. _ref1.step('contextualizeFiles').total(collection.length);
  2114. }
  2115. collection.forEach(function(file, index) {
  2116. return tasks.addTask(function(complete) {
  2117. return file.contextualize(function(err) {
  2118. var _ref2;
  2119. if ((_ref2 = opts.progress) != null) {
  2120. _ref2.tick();
  2121. }
  2122. return complete(err);
  2123. });
  2124. });
  2125. });
  2126. docpad.emitSync('contextualizeBefore', {
  2127. collection: collection,
  2128. templateData: templateData
  2129. }, function(err) {
  2130. if (err) {
  2131. return next(err);
  2132. }
  2133. return tasks.run();
  2134. });
  2135. return this;
  2136. };
  2137. DocPad.prototype.renderFiles = function(opts, next) {
  2138. var collection, docpad, initialCollection, locale, renderCollection, renderFile, renderPasses, subsequentCollection, tasks, templateData, _i, _results,
  2139. _this = this;
  2140. if (opts == null) {
  2141. opts = {};
  2142. }
  2143. docpad = this;
  2144. locale = this.getLocale();
  2145. collection = opts.collection, templateData = opts.templateData, renderPasses = opts.renderPasses;
  2146. docpad.log('debug', util.format(locale.renderingFiles, collection.length));
  2147. tasks = new TaskGroup().once('complete', function(err) {
  2148. if (err) {
  2149. return next(err);
  2150. }
  2151. return docpad.emitSync('renderAfter', {
  2152. collection: collection
  2153. }, function(err) {
  2154. if (err) {
  2155. return next(err);
  2156. }
  2157. docpad.log('debug', util.format(locale.renderedFiles, collection.length));
  2158. return next();
  2159. });
  2160. });
  2161. renderFile = function(fileToRender, next) {
  2162. var dynamic, relativePath, render;
  2163. dynamic = fileToRender.get('dynamic');
  2164. render = fileToRender.get('render');
  2165. relativePath = fileToRender.get('relativePath');
  2166. if (dynamic || ((render != null) && !render) || !relativePath || (fileToRender.render != null) === false) {
  2167. next();
  2168. } else {
  2169. fileToRender.render({
  2170. templateData: templateData
  2171. }, next);
  2172. }
  2173. return fileToRender;
  2174. };
  2175. renderCollection = function(collectionToRender, _arg, next) {
  2176. var renderPass, step, subTasks, _ref1;
  2177. renderPass = _arg.renderPass;
  2178. subTasks = new TaskGroup().setConfig({
  2179. concurrency: 0
  2180. }).once('complete', next);
  2181. step = "renderFiles (pass " + renderPass + ")";
  2182. if ((_ref1 = opts.progress) != null) {
  2183. _ref1.step(step).total(collectionToRender.length);
  2184. }
  2185. collectionToRender.forEach(function(file) {
  2186. return subTasks.addTask(function(complete) {
  2187. return renderFile(file, function(err) {
  2188. var _ref2;
  2189. if ((_ref2 = opts.progress) != null) {
  2190. _ref2.tick();
  2191. }
  2192. return complete(err);
  2193. });
  2194. });
  2195. });
  2196. subTasks.run();
  2197. return collectionToRender;
  2198. };
  2199. initialCollection = collection.findAll({
  2200. 'referencesOthers': false
  2201. });
  2202. subsequentCollection = null;
  2203. tasks.addTask(function(complete) {
  2204. return renderCollection(initialCollection, {
  2205. renderPass: 1
  2206. }, function(err) {
  2207. if (err) {
  2208. return complete(err);
  2209. }
  2210. subsequentCollection = collection.findAll({
  2211. 'referencesOthers': true
  2212. });
  2213. return renderCollection(subsequentCollection, {
  2214. renderPass: 2
  2215. }, complete);
  2216. });
  2217. });
  2218. if (renderPasses > 1) {
  2219. (function() {
  2220. _results = [];
  2221. for (var _i = 3; 3 <= renderPasses ? _i <= renderPasses : _i >= renderPasses; 3 <= renderPasses ? _i++ : _i--){ _results.push(_i); }
  2222. return _results;
  2223. }).apply(this).forEach(function(renderPass) {
  2224. return tasks.addTask(function(complete) {
  2225. return renderCollection(subsequentCollection, {
  2226. renderPass: renderPass
  2227. }, complete);
  2228. });
  2229. });
  2230. }
  2231. docpad.emitSync('renderBefore', {
  2232. collection: collection,
  2233. templateData: templateData
  2234. }, function(err) {
  2235. if (err) {
  2236. return next(err);
  2237. }
  2238. return tasks.run();
  2239. });
  2240. return this;
  2241. };
  2242. DocPad.prototype.writeFiles = function(opts, next) {
  2243. var collection, docpad, locale, tasks, templateData, _ref1,
  2244. _this = this;
  2245. if (opts == null) {
  2246. opts = {};
  2247. }
  2248. docpad = this;
  2249. locale = this.getLocale();
  2250. collection = opts.collection, templateData = opts.templateData;
  2251. docpad.log('debug', util.format(locale.writingFiles, collection.length));
  2252. tasks = new TaskGroup().setConfig({
  2253. concurrency: 0
  2254. }).once('complete', function(err) {
  2255. if (err) {
  2256. return next(err);
  2257. }
  2258. return docpad.emitSync('writeAfter', {
  2259. collection: collection
  2260. }, function(err) {
  2261. if (err) {
  2262. return next(err);
  2263. }
  2264. docpad.log('debug', util.format(locale.wroteFiles, collection.length));
  2265. return next();
  2266. });
  2267. });
  2268. if ((_ref1 = opts.progress) != null) {
  2269. _ref1.step('writeFiles').total(collection.length);
  2270. }
  2271. collection.forEach(function(file, index) {
  2272. return tasks.addTask(function(complete) {
  2273. var dynamic, err, finish, relativePath, write;
  2274. dynamic = file.get('dynamic');
  2275. write = file.get('write');
  2276. relativePath = file.get('relativePath');
  2277. finish = function(err) {
  2278. var _ref2;
  2279. if ((_ref2 = opts.progress) != null) {
  2280. _ref2.tick();
  2281. }
  2282. return complete(err);
  2283. };
  2284. if (dynamic || ((write != null) && !write) || !relativePath) {
  2285. return finish();
  2286. } else if (file.writeRendered != null) {
  2287. return file.writeRendered(finish);
  2288. } else if (file.write != null) {
  2289. return file.write(finish);
  2290. } else {
  2291. err = new Error(locale.unknownModelInCollection);
  2292. return finish(err);
  2293. }
  2294. });
  2295. });
  2296. docpad.emitSync('writeBefore', {
  2297. collection: collection,
  2298. templateData: templateData
  2299. }, function(err) {
  2300. if (err) {
  2301. return next(err);
  2302. }
  2303. return tasks.run();
  2304. });
  2305. return this;
  2306. };
  2307. DocPad.prototype.action = function(action, opts, next) {
  2308. var actions, docpad, forward, locale, runner, tasks, _ref1,
  2309. _this = this;
  2310. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2311. docpad = this;
  2312. runner = this.getActionRunner();
  2313. locale = this.getLocale();
  2314. if (typeChecker.isArray(action)) {
  2315. actions = action;
  2316. } else {
  2317. actions = action.split(/[,\s]+/g);
  2318. }
  2319. actions = _.uniq(_.compact(actions));
  2320. if (actions.length === 1) {
  2321. action = actions[0];
  2322. } else {
  2323. tasks = new TaskGroup().once('complete', function(err) {
  2324. return next(err);
  2325. });
  2326. actions.forEach(function(action) {
  2327. return tasks.addTask(function(complete) {
  2328. return docpad.action(action, opts, complete);
  2329. });
  2330. });
  2331. tasks.run();
  2332. return docpad;
  2333. }
  2334. this.log('debug', util.format(locale.actionStart, action));
  2335. if (next == null) {
  2336. next = function(err) {
  2337. if (err) {
  2338. return docpad.fatal(err);
  2339. }
  2340. };
  2341. }
  2342. forward = function() {
  2343. var args;
  2344. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  2345. _this.log('debug', util.format(locale.actionFinished, action));
  2346. return process.nextTick(function() {
  2347. return next.apply(null, args);
  2348. });
  2349. };
  2350. runner.addTask(function(complete) {
  2351. var fn;
  2352. fn = docpad[action];
  2353. if (!fn) {
  2354. return complete(new Error(util.format(locale.actionNonexistant, action)));
  2355. }
  2356. docpad.track(action);
  2357. return fn(opts, function() {
  2358. var args;
  2359. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  2360. forward.apply(null, args);
  2361. return complete();
  2362. });
  2363. });
  2364. return this;
  2365. };
  2366. DocPad.prototype.generatePrepare = function(opts, next) {
  2367. var config, docpad, locale, tasks, _ref1;
  2368. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2369. docpad = this;
  2370. config = this.getConfig();
  2371. locale = this.getLocale();
  2372. docpad.generating = true;
  2373. docpad.log('info', locale.renderGenerating);
  2374. docpad.notify((new Date()).toLocaleTimeString(), {
  2375. title: locale.renderGeneratingNotification
  2376. });
  2377. tasks = new TaskGroup().once('complete', next);
  2378. if (opts.reset === true) {
  2379. if (!docpad.hasPlugins()) {
  2380. docpad.log('warn', locale.renderNoPlugins);
  2381. }
  2382. tasks.addTask(function(complete) {
  2383. return safefs.exists(config.srcPath, function(exists) {
  2384. var err;
  2385. if (exists === false) {
  2386. err = new Error(locale.renderNonexistant);
  2387. return complete(err);
  2388. } else {
  2389. return complete();
  2390. }
  2391. });
  2392. });
  2393. tasks.addTask(function(complete) {
  2394. return docpad.resetCollections(complete);
  2395. });
  2396. }
  2397. tasks.addTask(function(complete) {
  2398. return docpad.emitSync('generateBefore', {
  2399. reset: opts.reset,
  2400. server: docpad.getServer()
  2401. }, complete);
  2402. });
  2403. tasks.run();
  2404. return this;
  2405. };
  2406. DocPad.prototype.generateParse = function(opts, next) {
  2407. var config, database, docpad, locale, _ref1;
  2408. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2409. docpad = this;
  2410. database = this.getDatabase();
  2411. config = this.getConfig();
  2412. locale = this.getLocale();
  2413. this.emitSync('parseBefore', {}, function(err) {
  2414. var tasks;
  2415. if (err) {
  2416. return next(err);
  2417. }
  2418. docpad.log('debug', locale.renderParsing);
  2419. tasks = new TaskGroup().setConfig({
  2420. concurrency: 0
  2421. }).once('complete', function(err) {
  2422. if (err) {
  2423. return next(err);
  2424. }
  2425. return docpad.emitSync('parseAfter', {}, function(err) {
  2426. if (err) {
  2427. return next(err);
  2428. }
  2429. docpad.log('debug', locale.renderParsed);
  2430. return next(err);
  2431. });
  2432. });
  2433. config.documentsPaths.forEach(function(documentsPath) {
  2434. return tasks.addTask(function(complete) {
  2435. return docpad.parseDocumentDirectory({
  2436. path: documentsPath,
  2437. collection: database
  2438. }, complete);
  2439. });
  2440. });
  2441. config.filesPaths.forEach(function(filesPath) {
  2442. return tasks.addTask(function(complete) {
  2443. return docpad.parseFileDirectory({
  2444. path: filesPath,
  2445. collection: database
  2446. }, complete);
  2447. });
  2448. });
  2449. config.layoutsPaths.forEach(function(layoutsPath) {
  2450. return tasks.addTask(function(complete) {
  2451. return docpad.parseDocumentDirectory({
  2452. path: layoutsPath,
  2453. collection: database
  2454. }, complete);
  2455. });
  2456. });
  2457. return tasks.run();
  2458. });
  2459. return this;
  2460. };
  2461. DocPad.prototype.generateRender = function(opts, next) {
  2462. var docpad, _ref1;
  2463. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2464. docpad = this;
  2465. opts.templateData || (opts.templateData = this.getTemplateData());
  2466. opts.collection || (opts.collection = this.getDatabase());
  2467. opts.renderPasses || (opts.renderPasses = this.getConfig().renderPasses);
  2468. balUtil.flow({
  2469. object: docpad,
  2470. action: 'contextualizeFiles renderFiles writeFiles',
  2471. args: [opts],
  2472. next: function(err) {
  2473. return next(err);
  2474. }
  2475. });
  2476. return this;
  2477. };
  2478. DocPad.prototype.generatePostpare = function(opts, next) {
  2479. var collection, database, docpad, locale, _ref1;
  2480. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2481. docpad = this;
  2482. locale = this.getLocale();
  2483. database = this.getDatabase();
  2484. collection = opts.collection || database;
  2485. docpad.generating = false;
  2486. docpad.generateEnded = new Date();
  2487. docpad.databaseCache = null;
  2488. docpad.emitSync('generateAfter', {
  2489. server: docpad.getServer()
  2490. }, function(err) {
  2491. var howMany, seconds, _ref2;
  2492. if (err) {
  2493. return next(err);
  2494. }
  2495. seconds = (docpad.generateEnded - docpad.generateStarted) / 1000;
  2496. howMany = collection === database ? "all " + collection.length : collection.length;
  2497. if ((_ref2 = opts.progress) != null) {
  2498. _ref2.finish();
  2499. }
  2500. docpad.log('info', util.format(locale.renderGenerated, howMany, seconds));
  2501. docpad.notify((new Date()).toLocaleTimeString(), {
  2502. title: locale.renderGeneratedNotification
  2503. });
  2504. return next();
  2505. });
  2506. return this;
  2507. };
  2508. DocPad.prototype.generateStarted = null;
  2509. DocPad.prototype.generateEnded = null;
  2510. DocPad.prototype.generating = false;
  2511. DocPad.prototype.generate = function(opts, next) {
  2512. var config, docpad, finish, locale, _ref1, _ref2, _ref3, _ref4;
  2513. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2514. docpad = this;
  2515. config = this.getConfig();
  2516. locale = this.getLocale();
  2517. if ((_ref2 = opts.reset) == null) {
  2518. opts.reset = true;
  2519. }
  2520. if (((_ref3 = opts.collection) != null ? _ref3.length : void 0) === 0) {
  2521. return next();
  2522. }
  2523. if (config.prompts && this.getLogLevel() === 6) {
  2524. if ((_ref4 = opts.progress) == null) {
  2525. opts.progress = require('progressbar').create();
  2526. }
  2527. docpad.getLoggers().console.unpipe(process.stdout);
  2528. }
  2529. finish = function(err) {
  2530. if (opts.progress) {
  2531. opts.progress.finish();
  2532. opts.progress = null;
  2533. docpad.getLoggers().console.pipe(process.stdout);
  2534. }
  2535. return next(err);
  2536. };
  2537. if ((opts.collection != null) === false && opts.reset === false) {
  2538. docpad.generatePrepare(opts, function(err) {
  2539. var database, filesToReload;
  2540. if (err) {
  2541. return finish(err);
  2542. }
  2543. database = docpad.getDatabase();
  2544. filesToReload = opts.filesToReload || new FilesCollection();
  2545. filesToReload.add(database.findAll({
  2546. mtime: {
  2547. $gte: docpad.generateStarted
  2548. }
  2549. }).models);
  2550. docpad.generateStarted = new Date();
  2551. return docpad.loadFiles({
  2552. collection: filesToReload
  2553. }, function(err) {
  2554. var allStandalone, filesToRender;
  2555. if (err) {
  2556. return finish(err);
  2557. }
  2558. filesToRender = opts.filesToRender || new FilesCollection();
  2559. filesToRender.on('add', function(fileToRender) {
  2560. if (fileToRender.get('isLayout')) {
  2561. return filesToRender.add(database.findAll({
  2562. layoutId: fileToRender.id
  2563. }).models);
  2564. }
  2565. });
  2566. allStandalone = true;
  2567. filesToReload.forEach(function(fileToReload) {
  2568. if (fileToReload.get('standalone') !== true) {
  2569. allStandalone = false;
  2570. return false;
  2571. }
  2572. });
  2573. if (allStandalone === false) {
  2574. filesToRender.add(database.findAll({
  2575. referencesOthers: true
  2576. }).models);
  2577. }
  2578. filesToRender.add(filesToReload.models);
  2579. return docpad.generateRender({
  2580. collection: filesToRender
  2581. }, function(err) {
  2582. if (err) {
  2583. return finish(err);
  2584. }
  2585. return docpad.generatePostpare({
  2586. collection: filesToRender
  2587. }, function(err) {
  2588. return finish(err);
  2589. });
  2590. });
  2591. });
  2592. });
  2593. } else {
  2594. docpad.generateStarted = new Date();
  2595. balUtil.flow({
  2596. object: docpad,
  2597. action: 'generatePrepare generateParse generateRender generatePostpare',
  2598. args: [opts],
  2599. next: function(err) {
  2600. return finish(err);
  2601. }
  2602. });
  2603. }
  2604. return this;
  2605. };
  2606. DocPad.prototype.flowDocument = function(document, opts, next) {
  2607. var _ref1;
  2608. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2609. balUtil.flow({
  2610. object: document,
  2611. action: opts.action,
  2612. args: [opts],
  2613. next: function(err) {
  2614. return typeof next === "function" ? next(err, document) : void 0;
  2615. }
  2616. });
  2617. return this;
  2618. };
  2619. DocPad.prototype.loadDocument = function(document, opts, next) {
  2620. var _ref1;
  2621. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2622. opts.action || (opts.action = 'load contextualize');
  2623. this.flowDocument(document, opts, next);
  2624. return this;
  2625. };
  2626. DocPad.prototype.loadAndRenderDocument = function(document, opts, next) {
  2627. var _ref1;
  2628. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2629. opts.action || (opts.action = 'load contextualize render');
  2630. this.flowDocument(document, opts, function(err) {
  2631. var result;
  2632. result = document.getOutContent();
  2633. return typeof next === "function" ? next(err, result, document) : void 0;
  2634. });
  2635. return this;
  2636. };
  2637. DocPad.prototype.renderDocument = function(document, opts, next) {
  2638. var _ref1;
  2639. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2640. document.render(opts, next);
  2641. return this;
  2642. };
  2643. DocPad.prototype.renderPath = function(path, opts, next) {
  2644. var attributes, document, _ref1;
  2645. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2646. attributes = extendr.extend({
  2647. fullPath: path
  2648. }, opts.attributes);
  2649. document = this.ensureDocument(attributes);
  2650. this.loadAndRenderDocument(document, opts, next);
  2651. return this;
  2652. };
  2653. DocPad.prototype.renderData = function(content, opts, next) {
  2654. var attributes, document, _ref1;
  2655. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2656. attributes = extendr.extend({
  2657. filename: opts.filename,
  2658. data: content
  2659. }, opts.attributes);
  2660. document = this.createDocument(attributes);
  2661. this.loadAndRenderDocument(document, opts, next);
  2662. return this;
  2663. };
  2664. DocPad.prototype.renderText = function(text, opts, next) {
  2665. var attributes, document, _ref1, _ref2;
  2666. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2667. if ((_ref2 = opts.actions) == null) {
  2668. opts.actions = ['renderExtensions', 'renderDocument'];
  2669. }
  2670. attributes = extendr.extend({
  2671. filename: opts.filename,
  2672. data: text,
  2673. body: text,
  2674. content: text
  2675. }, opts.attributes);
  2676. document = this.createDocument(attributes);
  2677. balUtil.flow({
  2678. object: document,
  2679. action: 'normalize contextualize render',
  2680. args: [opts],
  2681. next: function(err) {
  2682. var result;
  2683. result = document.getOutContent();
  2684. return next(err, result, document);
  2685. }
  2686. });
  2687. return this;
  2688. };
  2689. DocPad.prototype.render = function(opts, next) {
  2690. var err, locale, path, _ref1;
  2691. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2692. locale = this.getLocale();
  2693. if (opts.document) {
  2694. this.renderDocument(opts.document, opts, next);
  2695. } else if (opts.data) {
  2696. this.renderData(opts.data, opts, next);
  2697. } else if (opts.text) {
  2698. this.renderText(opts.text, opts, next);
  2699. } else {
  2700. path = opts.path || opts.fullPath || opts.filename || null;
  2701. if (path) {
  2702. this.renderPath(path, opts, next);
  2703. } else {
  2704. err = new Error(locale.renderInvalidOptions);
  2705. return next(err);
  2706. }
  2707. }
  2708. return this;
  2709. };
  2710. DocPad.prototype.watch = function(opts, next) {
  2711. var changeHandler, closeWatchers, config, database, docpad, locale, performGenerate, queueRegeneration, regenerateTimer, resetWatchers, watchers, _ref1;
  2712. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2713. docpad = this;
  2714. config = this.getConfig();
  2715. locale = this.getLocale();
  2716. database = this.getDatabase();
  2717. watchers = [];
  2718. closeWatchers = function() {
  2719. var watcher, _i, _len;
  2720. for (_i = 0, _len = watchers.length; _i < _len; _i++) {
  2721. watcher = watchers[_i];
  2722. watcher.close();
  2723. watcher = null;
  2724. }
  2725. return watchers = [];
  2726. };
  2727. resetWatchers = function(next) {
  2728. var regeneratePaths, reloadPaths, srcPath, tasks;
  2729. closeWatchers();
  2730. tasks = new TaskGroup().setConfig({
  2731. concurrency: 0
  2732. }).once('complete', next);
  2733. reloadPaths = _.union(config.reloadPaths, config.configPaths);
  2734. tasks.addTask(function(complete) {
  2735. return docpad.watchdir({
  2736. paths: reloadPaths,
  2737. listeners: {
  2738. 'log': docpad.log,
  2739. 'error': docpad.error,
  2740. 'change': function() {
  2741. docpad.log('info', util.format(locale.watchReloadChange, new Date().toLocaleTimeString()));
  2742. return docpad.action('load', function(err) {
  2743. if (err) {
  2744. return docpad.fatal(err);
  2745. }
  2746. return performGenerate({
  2747. reset: true
  2748. });
  2749. });
  2750. }
  2751. },
  2752. next: function(err, _watchers) {
  2753. var watcher, _i, _len;
  2754. if (err) {
  2755. docpad.log('warn', "Watching the reload paths has failed:", reloadPaths, err);
  2756. return complete();
  2757. }
  2758. for (_i = 0, _len = _watchers.length; _i < _len; _i++) {
  2759. watcher = _watchers[_i];
  2760. watchers.push(watcher);
  2761. }
  2762. return complete();
  2763. }
  2764. });
  2765. });
  2766. regeneratePaths = config.regeneratePaths;
  2767. tasks.addTask(function(complete) {
  2768. return docpad.watchdir({
  2769. paths: regeneratePaths,
  2770. listeners: {
  2771. 'log': docpad.log,
  2772. 'error': docpad.error,
  2773. 'change': function() {
  2774. return performGenerate({
  2775. reset: true
  2776. });
  2777. }
  2778. },
  2779. next: function(err, _watchers) {
  2780. var watcher, _i, _len;
  2781. if (err) {
  2782. docpad.log('warn', "Watching the regenerate paths has failed:", regeneratePaths, err);
  2783. return complete();
  2784. }
  2785. for (_i = 0, _len = _watchers.length; _i < _len; _i++) {
  2786. watcher = _watchers[_i];
  2787. watchers.push(watcher);
  2788. }
  2789. return complete();
  2790. }
  2791. });
  2792. });
  2793. srcPath = config.srcPath;
  2794. tasks.addTask(function(complete) {
  2795. return docpad.watchdir({
  2796. path: srcPath,
  2797. listeners: {
  2798. 'log': docpad.log,
  2799. 'error': docpad.error,
  2800. 'change': changeHandler
  2801. },
  2802. next: function(err, watcher) {
  2803. if (err) {
  2804. docpad.log('warn', "Watching the src path has failed:", srcPath, err);
  2805. return complete();
  2806. }
  2807. watchers.push(watcher);
  2808. return complete();
  2809. }
  2810. });
  2811. });
  2812. return tasks.run();
  2813. };
  2814. regenerateTimer = null;
  2815. queueRegeneration = function() {
  2816. if (regenerateTimer) {
  2817. clearTimeout(regenerateTimer);
  2818. regenerateTimer = null;
  2819. }
  2820. return regenerateTimer = setTimeout(performGenerate, config.regenerateDelay);
  2821. };
  2822. performGenerate = function(opts) {
  2823. var _ref2;
  2824. opts || (opts = {});
  2825. if ((_ref2 = opts.reset) == null) {
  2826. opts.reset = false;
  2827. }
  2828. docpad.log(util.format(locale.watchRegenerating, new Date().toLocaleTimeString()));
  2829. return docpad.action('generate', opts, function(err) {
  2830. if (err) {
  2831. docpad.error(err);
  2832. }
  2833. return docpad.log(util.format(locale.watchRegenerated, new Date().toLocaleTimeString()));
  2834. });
  2835. };
  2836. changeHandler = function(changeType, filePath, fileCurrentStat, filePreviousStat) {
  2837. var file, isDirectory, isIgnored;
  2838. docpad.log('debug', util.format(locale.watchChange, new Date().toLocaleTimeString()), changeType, filePath);
  2839. isIgnored = docpad.isIgnoredPath(filePath);
  2840. if (isIgnored) {
  2841. docpad.log('debug', util.format(locale.watchIgnoredChange, new Date().toLocaleTimeString()), filePath);
  2842. return;
  2843. }
  2844. isDirectory = (fileCurrentStat || filePreviousStat).isDirectory();
  2845. if (isDirectory) {
  2846. docpad.log('debug', util.format(locale.watchDirectoryChange, new Date().toLocaleTimeString()), filePath);
  2847. return;
  2848. }
  2849. if (fileCurrentStat != null) {
  2850. fileCurrentStat.mtime = new Date();
  2851. }
  2852. file = docpad.ensureFileOrDocument({
  2853. fullPath: filePath
  2854. }, {
  2855. stat: fileCurrentStat
  2856. });
  2857. if (changeType === 'update') {
  2858. file.setStat(fileCurrentStat);
  2859. }
  2860. if (changeType === 'delete') {
  2861. database.remove(file);
  2862. return file["delete"](function(err) {
  2863. if (err) {
  2864. return docpad.error(err);
  2865. }
  2866. return queueRegeneration();
  2867. });
  2868. } else if (changeType === 'create' || changeType === 'update') {
  2869. return queueRegeneration();
  2870. }
  2871. };
  2872. docpad.log(locale.watchStart);
  2873. resetWatchers(function(err) {
  2874. if (err) {
  2875. return next(err);
  2876. }
  2877. docpad.log(locale.watchStarted);
  2878. return next();
  2879. });
  2880. return this;
  2881. };
  2882. DocPad.prototype.run = function(opts, next) {
  2883. var destinationPath, docpad, locale, runDocpad, srcPath, _ref1;
  2884. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2885. docpad = this;
  2886. srcPath = this.config.srcPath;
  2887. destinationPath = this.config.rootPath;
  2888. locale = this.getLocale();
  2889. runDocpad = function() {
  2890. return balUtil.flow({
  2891. object: docpad,
  2892. action: 'server generate watch',
  2893. args: [opts],
  2894. next: function(err) {
  2895. return next(err);
  2896. }
  2897. });
  2898. };
  2899. if (safefs.existsSync(srcPath)) {
  2900. runDocpad();
  2901. } else {
  2902. safefs.readdir(destinationPath, function(err, files) {
  2903. if (err) {
  2904. return next(err);
  2905. }
  2906. if (files.length) {
  2907. docpad.log('warn', "\n" + util.format(locale.skeletonNonexistant, destinationPath));
  2908. return next();
  2909. } else {
  2910. return docpad.skeleton(opts, function(err) {
  2911. if (err) {
  2912. return next(err);
  2913. }
  2914. return runDocpad();
  2915. });
  2916. }
  2917. });
  2918. }
  2919. return this;
  2920. };
  2921. DocPad.prototype.skeleton = function(opts, next) {
  2922. var config, destinationPath, docpad, locale, selectSkeletonCallback, skeletonId, srcPath, useNoSkeleton, useSkeleton, _ref1;
  2923. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  2924. docpad = this;
  2925. config = this.getConfig();
  2926. skeletonId = config.skeleton;
  2927. srcPath = config.srcPath;
  2928. destinationPath = config.rootPath;
  2929. selectSkeletonCallback = opts.selectSkeletonCallback || null;
  2930. locale = this.getLocale();
  2931. useSkeleton = function(skeletonModel) {
  2932. docpad.track('skeleton-use', {
  2933. skeletonId: skeletonModel.id
  2934. });
  2935. docpad.log('info', util.format(locale.skeletonInstall, skeletonModel.get('name'), destinationPath));
  2936. return docpad.installSkeleton(skeletonModel, destinationPath, function(err) {
  2937. if (err) {
  2938. return next(err);
  2939. }
  2940. return docpad.load(function(err) {
  2941. if (err) {
  2942. return next(err);
  2943. }
  2944. docpad.log('info', locale.skeletonInstalled);
  2945. return next(err);
  2946. });
  2947. });
  2948. };
  2949. useNoSkeleton = function() {
  2950. docpad.track('skeleton-use', {
  2951. skeletonId: 'none'
  2952. });
  2953. return safefs.ensurePath(srcPath, function(err) {
  2954. var tasks;
  2955. if (err) {
  2956. return next(err);
  2957. }
  2958. tasks = new TaskGroup().setConfig({
  2959. concurrency: 0
  2960. }).once('complete', next);
  2961. tasks.addTask(function(complete) {
  2962. return safefs.ensurePath(pathUtil.join(config.rootPath, 'node_modules'), complete);
  2963. });
  2964. tasks.addTask(function(complete) {
  2965. var data;
  2966. data = JSON.stringify({
  2967. name: 'no-skeleton.docpad',
  2968. version: '0.1.0',
  2969. description: 'New DocPad project without using a skeleton',
  2970. engines: {
  2971. node: '0.10',
  2972. npm: '1.2'
  2973. },
  2974. dependencies: {
  2975. docpad: '6.x'
  2976. },
  2977. main: 'node_modules/docpad/bin/docpad-server'
  2978. }, null, '\t');
  2979. return safefs.writeFile(pathUtil.join(config.rootPath, 'package.json'), data, complete);
  2980. });
  2981. tasks.addTask(function(complete) {
  2982. var data;
  2983. data = "# DocPad Configuration File\n# http://docpad.org/docs/config\n\n# Define the DocPad Configuration\ndocpadConfig = {\n # ...\n}\n\n# Export the DocPad Configuration\nmodule.exports = docpadConfig";
  2984. return safefs.writeFile(pathUtil.join(config.rootPath, 'docpad.coffee'), data, complete);
  2985. });
  2986. tasks.addTask(function(complete) {
  2987. return safefs.ensurePath(config.documentsPaths[0], complete);
  2988. });
  2989. tasks.addTask(function(complete) {
  2990. return safefs.ensurePath(config.layoutsPaths[0], complete);
  2991. });
  2992. tasks.addTask(function(complete) {
  2993. return safefs.ensurePath(config.filesPaths[0], complete);
  2994. });
  2995. return tasks.run();
  2996. });
  2997. };
  2998. safefs.exists(srcPath, function(exists) {
  2999. if (exists) {
  3000. docpad.log('warn', locale.skeletonExists);
  3001. return next();
  3002. }
  3003. docpad.track('skeleton-ask');
  3004. if (skeletonId) {
  3005. return useSkeleton();
  3006. } else {
  3007. return docpad.getSkeletons(function(err, skeletonsCollection) {
  3008. if (err) {
  3009. return next(err);
  3010. }
  3011. return selectSkeletonCallback(skeletonsCollection, function(err, skeletonModel) {
  3012. if (err) {
  3013. return next(err);
  3014. }
  3015. if ((skeletonModel != null) === false || skeletonModel.id === 'none') {
  3016. return useNoSkeleton();
  3017. } else {
  3018. return useSkeleton(skeletonModel);
  3019. }
  3020. });
  3021. });
  3022. }
  3023. });
  3024. return this;
  3025. };
  3026. DocPad.prototype.serveDocument = function(opts, next) {
  3027. var content, contentType, docpad, document, dynamic, err, req, res, templateData, _ref1;
  3028. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  3029. document = opts.document, err = opts.err, req = opts.req, res = opts.res;
  3030. docpad = this;
  3031. if (!document) {
  3032. if (opts.statusCode != null) {
  3033. return res.send(opts.statusCode);
  3034. } else {
  3035. return next();
  3036. }
  3037. }
  3038. contentType = document.get('outContentType') || document.get('contentType');
  3039. res.setHeader('Content-Type', contentType);
  3040. dynamic = document.get('dynamic');
  3041. if (dynamic) {
  3042. templateData = extendr.extend({}, req.templateData || {}, {
  3043. req: req,
  3044. err: err
  3045. });
  3046. templateData = docpad.getTemplateData(templateData);
  3047. document.render({
  3048. templateData: templateData
  3049. }, function(err) {
  3050. var content;
  3051. content = document.getOutContent();
  3052. if (err) {
  3053. docpad.error(err);
  3054. return next(err);
  3055. } else {
  3056. if (opts.statusCode != null) {
  3057. return res.send(opts.statusCode, content);
  3058. } else {
  3059. return res.send(content);
  3060. }
  3061. }
  3062. });
  3063. } else {
  3064. content = document.getOutContent();
  3065. if (content) {
  3066. if (opts.statusCode != null) {
  3067. return res.send(opts.statusCode, content);
  3068. } else {
  3069. return res.send(content);
  3070. }
  3071. } else {
  3072. if (opts.statusCode != null) {
  3073. return res.send(opts.statusCode);
  3074. } else {
  3075. return next();
  3076. }
  3077. }
  3078. }
  3079. return this;
  3080. };
  3081. DocPad.prototype.serverMiddlewareHeader = function(req, res, next) {
  3082. var docpad, tools;
  3083. docpad = this;
  3084. tools = res.get('X-Powered-By').split(/[,\s]+/g);
  3085. tools.push("DocPad v" + docpad.version);
  3086. tools = tools.join(',');
  3087. res.set('X-Powered-By', tools);
  3088. next();
  3089. return this;
  3090. };
  3091. DocPad.prototype.serverMiddlewareRouter = function(req, res, next) {
  3092. var cleanUrl, database, docpad, file, url;
  3093. docpad = this;
  3094. if (docpad.generateEnded === null) {
  3095. docpad.once('generateAfter', function() {
  3096. return docpad.serverMiddlewareRouter(req, res, next);
  3097. });
  3098. return this;
  3099. }
  3100. database = docpad.getDatabaseCache();
  3101. cleanUrl = req.url.replace(/\?.*/, '');
  3102. file = docpad.getFileByUrl(req.url, {
  3103. collection: database
  3104. }) || docpad.getFileByUrl(cleanUrl, {
  3105. collection: database
  3106. });
  3107. if ((file != null) === false) {
  3108. return next();
  3109. }
  3110. url = file.get('url');
  3111. if ((url !== cleanUrl) && (url !== req.url)) {
  3112. return res.redirect(301, url);
  3113. }
  3114. docpad.serveDocument({
  3115. document: file,
  3116. req: req,
  3117. res: res,
  3118. next: next
  3119. });
  3120. return this;
  3121. };
  3122. DocPad.prototype.serverMiddleware404 = function(req, res, next) {
  3123. var database, docpad, document;
  3124. docpad = this;
  3125. database = docpad.getDatabaseCache();
  3126. if (!database) {
  3127. return res.send(500);
  3128. }
  3129. document = database.findOne({
  3130. relativeOutPath: '404.html'
  3131. });
  3132. docpad.serveDocument({
  3133. document: document,
  3134. req: req,
  3135. res: res,
  3136. next: next,
  3137. statusCode: 404
  3138. });
  3139. return this;
  3140. };
  3141. DocPad.prototype.serverMiddleware500 = function(err, req, res, next) {
  3142. var database, docpad, document;
  3143. docpad = this;
  3144. database = docpad.getDatabaseCache();
  3145. if (!database) {
  3146. return res.send(500);
  3147. }
  3148. document = database.findOne({
  3149. relativeOutPath: '500.html'
  3150. });
  3151. docpad.serveDocument({
  3152. document: document,
  3153. err: err,
  3154. req: req,
  3155. res: res,
  3156. next: next,
  3157. statusCode: 500
  3158. });
  3159. return this;
  3160. };
  3161. DocPad.prototype.server = function(opts, next) {
  3162. var config, docpad, express, finish, http, locale, port, serverExpress, serverHttp, startServer, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
  3163. http = null;
  3164. express = null;
  3165. _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1];
  3166. docpad = this;
  3167. config = this.config;
  3168. locale = this.getLocale();
  3169. port = this.getPort();
  3170. serverExpress = null;
  3171. serverHttp = null;
  3172. if ((_ref2 = opts.middlewareBodyParser) == null) {
  3173. opts.middlewareBodyParser = (_ref3 = config.middlewareBodyParser) != null ? _ref3 : config.middlewareStandard;
  3174. }
  3175. if ((_ref4 = opts.middlewareMethodOverride) == null) {
  3176. opts.middlewareMethodOverride = (_ref5 = config.middlewareMethodOverride) != null ? _ref5 : config.middlewareStandard;
  3177. }
  3178. if ((_ref6 = opts.middlewareExpressRouter) == null) {
  3179. opts.middlewareExpressRouter = (_ref7 = config.middlewareExpressRouter) != null ? _ref7 : config.middlewareStandard;
  3180. }
  3181. if ((_ref8 = opts.middleware404) == null) {
  3182. opts.middleware404 = config.middleware404;
  3183. }
  3184. if ((_ref9 = opts.middleware500) == null) {
  3185. opts.middleware500 = config.middleware500;
  3186. }
  3187. finish = function(err) {
  3188. if (err) {
  3189. return next(err);
  3190. }
  3191. return docpad.emitSync('serverAfter', {
  3192. server: serverExpress,
  3193. serverExpress: serverExpress,
  3194. serverHttp: serverHttp,
  3195. express: express
  3196. }, function(err) {
  3197. if (err) {
  3198. return next(err);
  3199. }
  3200. return next();
  3201. });
  3202. };
  3203. startServer = function(next) {
  3204. serverHttp.once('error', function(err) {
  3205. if (err.message.indexOf('EADDRINUSE') !== -1) {
  3206. err = new Error(util.format(locale.serverInUse, port));
  3207. }
  3208. return next(err);
  3209. });
  3210. docpad.log('debug', util.format(locale.serverStart, port, config.outPath));
  3211. return serverHttp.listen(port, function() {
  3212. var address, serverHostname, serverLocation, serverPort;
  3213. address = serverHttp.address();
  3214. serverHostname = address.address === '0.0.0.0' ? 'localhost' : address.address;
  3215. serverPort = address.port;
  3216. serverLocation = "http://" + serverHostname + ":" + serverPort + "/";
  3217. docpad.log('info', util.format(locale.serverStarted, serverLocation, config.outPath));
  3218. return next();
  3219. });
  3220. };
  3221. docpad.emitSync('serverBefore', {}, function(err) {
  3222. var _ref10;
  3223. if (err) {
  3224. return finish(err);
  3225. }
  3226. _ref10 = docpad.getServer(true), serverExpress = _ref10.serverExpress, serverHttp = _ref10.serverHttp;
  3227. if (!serverExpress && !serverHttp) {
  3228. if (http == null) {
  3229. http = require('http');
  3230. }
  3231. if (express == null) {
  3232. express = require('express');
  3233. }
  3234. serverExpress = opts.serverExpress || express();
  3235. serverHttp = opts.serverHttp || http.createServer(serverExpress);
  3236. docpad.setServer({
  3237. serverExpress: serverExpress,
  3238. serverHttp: serverHttp
  3239. });
  3240. }
  3241. if (!config.extendServer) {
  3242. return startServer(finish);
  3243. } else {
  3244. if (express == null) {
  3245. express = require('express');
  3246. }
  3247. if (opts.middlewareBodyParser !== false) {
  3248. serverExpress.use(express.bodyParser());
  3249. }
  3250. if (opts.middlewareMethodOverride !== false) {
  3251. serverExpress.use(express.methodOverride());
  3252. }
  3253. docpad.emitSync('serverExtend', {
  3254. server: serverExpress,
  3255. serverExpress: serverExpress,
  3256. serverHttp: serverHttp,
  3257. express: express
  3258. }, function(err) {
  3259. if (err) {
  3260. return next(err);
  3261. }
  3262. serverExpress.use(docpad.serverMiddlewareHeader);
  3263. if (opts.middlewareExpressRouter !== false) {
  3264. serverExpress.use(serverExpress.router);
  3265. }
  3266. serverExpress.use(docpad.serverMiddlewareRouter);
  3267. if (config.maxAge) {
  3268. serverExpress.use(express["static"](config.outPath, {
  3269. maxAge: config.maxAge
  3270. }));
  3271. } else {
  3272. serverExpress.use(express["static"](config.outPath));
  3273. }
  3274. if (opts.middleware404 !== false) {
  3275. serverExpress.use(docpad.serverMiddleware404);
  3276. }
  3277. if (opts.middleware500 !== false) {
  3278. return serverExpress.error(docpad.serverMiddleware500);
  3279. }
  3280. });
  3281. return startServer(finish);
  3282. }
  3283. });
  3284. return this;
  3285. };
  3286. return DocPad;
  3287. })(EventEmitterEnhanced);
  3288. module.exports = {
  3289. DocPad: DocPad,
  3290. queryEngine: queryEngine,
  3291. Backbone: Backbone,
  3292. createInstance: function() {
  3293. var args;
  3294. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3295. return (function(func, args, ctor) {
  3296. ctor.prototype = func.prototype;
  3297. var child = new ctor, result = func.apply(child, args);
  3298. return Object(result) === result ? result : child;
  3299. })(DocPad, args, function(){});
  3300. }
  3301. };