// Generated by CoffeeScript 1.6.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, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __slice = [].slice; pathUtil = require('path'); _ = require('lodash'); CSON = require('cson'); balUtil = require('bal-util'); extendr = require('extendr'); eachr = require('eachr'); typeChecker = require('typechecker'); ambi = require('ambi'); TaskGroup = require('taskgroup').TaskGroup; safefs = require('safefs'); util = require('util'); canihaz = null; EventEmitterEnhanced = balUtil.EventEmitterEnhanced; _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; FileModel = require(__dirname + '/models/file'); DocumentModel = require(__dirname + '/models/document'); FilesCollection = require(__dirname + '/collections/files'); ElementsCollection = require(__dirname + '/collections/elements'); MetaCollection = require(__dirname + '/collections/meta'); ScriptsCollection = require(__dirname + '/collections/scripts'); StylesCollection = require(__dirname + '/collections/styles'); PluginLoader = require(__dirname + '/plugin-loader'); BasePlugin = require(__dirname + '/plugin'); /* The DocPad Class It extends the EventSystem from bal-util to provide system events It allows us to support multiple instances of docpad at the same time */ DocPad = (function(_super) { __extends(DocPad, _super); DocPad.prototype.Events = Events; DocPad.prototype.Model = Model; DocPad.prototype.Collection = Collection; DocPad.prototype.View = View; DocPad.prototype.QueryCollection = QueryCollection; DocPad.prototype.FileModel = FileModel; DocPad.prototype.DocumentModel = DocumentModel; DocPad.prototype.FilesCollection = FilesCollection; DocPad.prototype.ElementsCollection = ElementsCollection; DocPad.prototype.MetaCollection = MetaCollection; DocPad.prototype.ScriptsCollection = ScriptsCollection; DocPad.prototype.StylesCollection = StylesCollection; DocPad.prototype.PluginLoader = PluginLoader; DocPad.prototype.BasePlugin = BasePlugin; DocPad.prototype.growlInstance = null; DocPad.prototype.getGrowlInstance = function() { var err; if ((this.growlInstance != null) === false) { if (this.getConfig().growl) { try { this.growlInstance = require('growl'); } catch (_error) { err = _error; this.growlInstance = false; } } else { this.growlInstance = false; } } return this.growlInstance; }; DocPad.prototype.mixpanelInstance = null; DocPad.prototype.getMixpanelInstance = function() { var config, err, mixpanelToken, reportStatistics; if ((this.mixpanelInstance != null) === false) { config = this.getConfig(); reportStatistics = config.reportStatistics, mixpanelToken = config.mixpanelToken; if ((reportStatistics != null) && (mixpanelToken != null)) { if (reportStatistics && mixpanelToken) { try { this.mixpanelInstance = require('mixpanel').init(mixpanelToken); } catch (_error) { err = _error; this.mixpanelInstance = false; } } else { this.mixpanelInstance = false; } } else { this.mixpanelInstance = null; } } return this.mixpanelInstance; }; DocPad.prototype.airbrakeInstance = null; DocPad.prototype.getAirbrakeInstance = function() { var airbrakeToken, config, err, reportErrors; if ((this.airbrakeInstance != null) === false) { config = this.getConfig(); airbrakeToken = config.airbrakeToken, reportErrors = config.reportErrors; if (reportErrors === true && /win/.test(process.platform) === false) { try { this.airbrakeInstance = require('airbrake').createClientairbrakeToken(); } catch (_error) { err = _error; this.airbrakeInstance = false; } } else { this.airbrakeInstance = false; } } return this.airbrakeInstance; }; DocPad.prototype.version = null; DocPad.prototype.getVersion = function() { return this.version; }; DocPad.prototype.getProcessPlatform = function() { return process.platform; }; DocPad.prototype.getProcessVersion = function() { return process.version.replace(/^v/, ''); }; DocPad.prototype.serverExpress = null; DocPad.prototype.serverHttp = null; DocPad.prototype.getServer = function(both) { var serverExpress, serverHttp; serverExpress = this.serverExpress, serverHttp = this.serverHttp; if (both) { return { serverExpress: serverExpress, serverHttp: serverHttp }; } else { return serverExpress; } }; DocPad.prototype.setServer = function(servers) { this.serverExpress = servers.serverExpress; return this.serverHttp = servers.serverHttp; }; DocPad.prototype.loggerInstances = null; DocPad.prototype.getLogger = function() { var _ref1; return (_ref1 = this.loggerInstances) != null ? _ref1.logger : void 0; }; DocPad.prototype.getLoggers = function() { return this.loggerInstances; }; DocPad.prototype.setLoggers = function(loggers) { if (this.loggerInstances) { this.warn('Loggers have already been set'); } else { this.loggerInstances = loggers; } return loggers; }; DocPad.prototype.actionRunnerInstance = null; DocPad.prototype.getActionRunner = function() { return this.actionRunnerInstance; }; DocPad.prototype.errorRunnerInstance = null; DocPad.prototype.getErrorRunner = function() { return this.errorRunnerInstance; }; DocPad.prototype.trackRunnerInstance = null; DocPad.prototype.getTrackRunner = function() { return this.trackRunnerInstance; }; DocPad.prototype.events = ['extendTemplateData', 'extendCollections', 'docpadLoaded', 'docpadReady', 'consoleSetup', 'generateBefore', 'populateCollections', 'generateAfter', 'parseBefore', 'parseAfter', 'contextualizeBefore', 'contextualizeAfter', 'renderBefore', 'render', 'renderDocument', 'renderAfter', 'writeBefore', 'writeAfter', 'serverBefore', 'serverExtend', 'serverAfter']; DocPad.prototype.getEvents = function() { return this.events; }; DocPad.prototype.database = null; DocPad.prototype.databaseCache = null; DocPad.prototype.getDatabase = function() { return this.database; }; DocPad.prototype.getDatabaseCache = function() { return this.databaseCache || this.database; }; DocPad.prototype.filesByUrl = null; DocPad.prototype.filesBySelector = null; DocPad.prototype.filesByOutPath = null; DocPad.prototype.blocks = null; /* { # A collection of meta elements meta: null # Elements Collection # A collection of script elements scripts: null # Scripts Collection # Collection of style elements styles: null # Styles Collection } */ DocPad.prototype.getBlock = function(name, clone) { var block, classname; block = this.blocks[name]; if (clone) { classname = name[0].toUpperCase() + name.slice(1) + 'Collection'; block = new this[classname](block.models); } return block; }; DocPad.prototype.setBlock = function(name, value) { if (this.blocks[name] != null) { this.blocks[name].destroy(); if (value) { this.blocks[name] = value; } else { delete this.blocks[name]; } } else { this.blocks[name] = value; } return this; }; DocPad.prototype.getBlocks = function(blocks) { this.blocks; return this; }; DocPad.prototype.setBlocks = function(blocks) { var name, value; for (name in blocks) { if (!__hasProp.call(blocks, name)) continue; value = blocks[name]; this.setBlock(name, value); } return this; }; DocPad.prototype.collections = null; /* { # Documents collection documents: null # QueryEngine Collection # Files collection files: null # QueryEngine Collection # Layouts collection layouts: null # QueryEngine Collection } */ DocPad.prototype.getCollection = function(name) { return this.collections[name]; }; DocPad.prototype.setCollection = function(name, value) { if (this.collections[name] != null) { this.collections[name].destroy(); if (value) { this.collections[name] = value; } else { delete this.collections[name]; } } else { this.collections[name] = value; } return this; }; DocPad.prototype.getCollections = function() { return this.collections; }; DocPad.prototype.setCollections = function(collections) { var name, value; for (name in collections) { if (!__hasProp.call(collections, name)) continue; value = collections[name]; this.setCollection(name, value); } return this; }; DocPad.prototype.getFiles = function(query, sorting, paging) { var files, key; key = JSON.stringify({ query: query, sorting: sorting, paging: paging }); files = this.getCollection(key); if (!files) { files = this.getDatabase().findAllLive(query, sorting, paging); this.setCollection(key, files); } return files; }; DocPad.prototype.getFile = function(query, sorting, paging) { var file; file = this.getDatabase().findOne(query, sorting, paging); return file; }; DocPad.prototype.getFilesAtPath = function(path, sorting, paging) { var files, query; query = { $or: [ { relativePath: { $startsWith: path } }, { fullPath: { $startsWith: path } } ] }; files = this.getFiles(query, sorting, paging); return files; }; DocPad.prototype.getFileAtPath = function(path, sorting, paging) { var file; file = this.getDatabase().fuzzyFindOne(path, sorting, paging); return file; }; DocPad.prototype.getFileByUrl = function(url, opts) { var file, _ref1; if (opts == null) { opts = {}; } if ((_ref1 = opts.collection) == null) { opts.collection = this.getDatabase(); } file = opts.collection.get(this.filesByUrl[url]); return file; }; DocPad.prototype.getFileBySelector = function(selector, opts) { var file, _ref1; if (opts == null) { opts = {}; } if ((_ref1 = opts.collection) == null) { opts.collection = this.getDatabase(); } file = opts.collection.get(this.filesBySelector[selector]); if (!file) { file = opts.collection.fuzzyFindOne(selector); if (file) { this.filesBySelector[selector] = file.id; } } return file; }; DocPad.prototype.skeletonsCollection = null; DocPad.prototype.getSkeletons = function(next) { var docpad, locale; docpad = this; locale = this.getLocale(); if (this.skeletonsCollection != null) { return next(null, this.skeletonsCollection); } this.skeletonsCollection = new Collection(); this.skeletonsCollection.comparator = queryEngine.generateComparator({ position: 1, name: 1 }); this.getExchange(function(err, exchange) { var index, skeleton, skeletonKey, _ref1, _ref2, _ref3, _ref4; if (err) { return next(err); } index = 0; _ref1 = exchange.skeletons; for (skeletonKey in _ref1) { if (!__hasProp.call(_ref1, skeletonKey)) continue; skeleton = _ref1[skeletonKey]; if ((_ref2 = skeleton.id) == null) { skeleton.id = skeletonKey; } if ((_ref3 = skeleton.name) == null) { skeleton.name = skeletonKey; } if ((_ref4 = skeleton.position) == null) { skeleton.position = index; } docpad.skeletonsCollection.add(new Model(skeleton)); ++index; } docpad.skeletonsCollection.add(new Model({ id: 'none', name: locale.skeletonNoneName, description: locale.skeletonNoneDescription, position: Infinity })); return next(null, docpad.skeletonsCollection); }); return this; }; DocPad.prototype.slowPlugins = null; DocPad.prototype.loadedPlugins = null; DocPad.prototype.exchange = null; DocPad.prototype.corePath = pathUtil.join(__dirname, '..', '..'); DocPad.prototype.libPath = __dirname; DocPad.prototype.mainPath = pathUtil.join(__dirname, 'docpad'); DocPad.prototype.packagePath = pathUtil.join(__dirname, '..', '..', 'package.json'); DocPad.prototype.localePath = pathUtil.join(__dirname, '..', '..', 'locale'); DocPad.prototype.debugLogPath = pathUtil.join(process.cwd(), 'docpad-debug.log'); DocPad.prototype.userConfigPath = '.docpad.cson'; DocPad.prototype.initialTemplateData = null; DocPad.prototype.pluginsTemplateData = null; DocPad.prototype.getTemplateData = function(userTemplateData) { var docpad, locale, renderPasses, templateData, _base, _base1, _ref1; userTemplateData || (userTemplateData = {}); docpad = this; renderPasses = this.config.renderPasses; locale = this.getLocale(); if ((_ref1 = this.initialTemplateData) == null) { this.initialTemplateData = { site: {}, getEnvironment: function() { return docpad.getEnvironment(); }, getEnvironments: function() { return docpad.getEnvironments(); }, referencesOthers: function(flag) { var document; document = this.getDocument(); document.referencesOthers(); return null; }, getDocument: function() { return this.documentModel; }, getPath: function(path, parentPath) { var document; document = this.getDocument(); path = document.getPath(path, parentPath); return path; }, getFiles: function(query, sorting, paging) { var result; this.referencesOthers(); result = docpad.getFiles(query, sorting, paging); return result; }, getFile: function(query, sorting, paging) { var result; this.referencesOthers(); result = docpad.getFile(query, sorting, paging); return result; }, getFilesAtPath: function(path, sorting, paging) { var result; this.referencesOthers(); path = this.getPath(path); result = docpad.getFilesAtPath(path, sorting, paging); return result; }, getFileAtPath: function(relativePath) { var path, result; this.referencesOthers(); path = this.getPath(relativePath); result = docpad.getFileAtPath(path); return result; }, getDatabase: function() { this.referencesOthers(); return docpad.getDatabase(); }, getCollection: function(name) { this.referencesOthers(); return docpad.getCollection(name); }, getBlock: function(name) { return docpad.getBlock(name, true); }, include: function(subRelativePath, strict) { var err, file; if (strict == null) { strict = true; } file = this.getFileAtPath(subRelativePath); if (file) { if (strict && file.get('rendered') === false) { if (renderPasses === 1) { docpad.warn(util.format(locale.renderedEarlyViaInclude, subRelativePath)); } return null; } return file.getOutContent(); } else { err = new Error(util.format(locale.includeFailed, subRelativePath)); throw err; } } }; } templateData = extendr.extend({}, this.initialTemplateData, this.pluginsTemplateData, this.config.templateData, userTemplateData); (_base = templateData.site).date || (_base.date = new Date()); (_base1 = templateData.site).keywords || (_base1.keywords = []); if (typeChecker.isString(templateData.site.keywords)) { templateData.site.keywords = templateData.site.keywords.split(/,\s*/g); } return templateData; }; DocPad.prototype.locales = { en: CSON.parseFileSync(pathUtil.join(__dirname, '..', '..', 'locale', 'en.cson')) }; DocPad.prototype.locale = null; DocPad.prototype.localeCode = null; DocPad.prototype.getLocaleCode = function() { var localeCode, localeCodes, _i, _len; if ((this.localeCode != null) === false) { localeCode = null; localeCodes = [this.getConfig().localeCode, balUtil.getLocaleCode(), 'en_AU']; for (_i = 0, _len = localeCodes.length; _i < _len; _i++) { localeCode = localeCodes[_i]; if (localeCode && (this.locales[localeCode] != null)) { break; } } this.localeCode = localeCode.toLowerCase(); } return this.localeCode; }; DocPad.prototype.getLanguageCode = function() { var languageCode; if ((this.languageCode != null) === false) { languageCode = balUtil.getLanguageCode(this.getLocaleCode()); this.languageCode = languageCode.toLowerCase(); } return this.languageCode; }; DocPad.prototype.getCountryCode = function() { var countryCode; if ((this.countryCode != null) === false) { countryCode = balUtil.getCountryCode(this.getLocaleCode()); this.countryCode = countryCode.toLowerCase(); } return this.countryCode; }; DocPad.prototype.getLocale = function() { if ((this.locale != null) === false) { this.locale = this.locales[this.getLocaleCode()] || this.locales[this.getLanguageCode()] || this.locales['en']; } return this.locale; }; DocPad.prototype.getEnvironment = function() { var env; env = this.getConfig().env || 'development'; return env; }; DocPad.prototype.getEnvironments = function() { var env, envs; env = this.getEnvironment(); envs = env.split(/[, ]+/); return envs; }; DocPad.prototype.websitePackageConfig = null; DocPad.prototype.config = null; DocPad.prototype.instanceConfig = null; DocPad.prototype.websiteConfig = null; DocPad.prototype.userConfig = { name: null, email: null, username: null, subscribed: null, subscribeTryAgain: null }; DocPad.prototype.initialConfig = { force: false, enableUnlistedPlugins: true, enabledPlugins: {}, skipUnsupportedPlugins: true, plugins: {}, exchangeUrl: 'https://docpad.org/exchange.json', rootPath: process.cwd(), packagePath: 'package.json', latestPackageUrl: 'https://docpad.org/latest.json', configPaths: ['docpad.js', 'docpad.coffee', 'docpad.json', 'docpad.cson'], pluginPaths: [], pluginsPaths: ['node_modules', 'plugins'], reloadPaths: [], regeneratePaths: [], regenerateDelay: 100, outPath: 'out', srcPath: 'src', documentsPaths: ['documents'], filesPaths: ['files', 'public'], layoutsPaths: ['layouts'], ignorePaths: false, ignoreHiddenFiles: false, ignoreCommonPatterns: true, ignoreCustomPatterns: false, watchOptions: null, port: null, maxAge: 86400000, serverExpress: null, serverHttp: null, extendServer: true, middlewareStandard: true, middlewareBodyParser: true, middlewareMethodOverride: true, middlewareExpressRouter: true, middleware404: true, middleware500: true, logLevel: ((__indexOf.call(process.argv, '-d') >= 0) ? 7 : 6), logger: null, growl: true, catchExceptions: true, reportErrors: process.argv.join('').indexOf('test') === -1, reportStatistics: process.argv.join('').indexOf('test') === -1, hashKey: '7>9}$3hP86o,4=@T', airbrakeToken: 'e7374dd1c5a346efe3895b9b0c1c0325', mixpanelToken: 'd0f9b33c0ec921350b5419352028577e', detectEncoding: false, renderSingleExtensions: false, renderPasses: 1, checkVersion: false, welcome: false, prompts: false, helperUrl: 'https://docpad.org/helper/', safeMode: false, templateData: {}, collections: {}, events: {}, regenerateEvery: false, localeCode: null, env: null, environments: { development: { maxAge: false, checkVersion: process.argv.length >= 2 && /docpad$/.test(process.argv[1]), welcome: process.argv.length >= 2 && /docpad$/.test(process.argv[1]), prompts: process.argv.length >= 2 && /docpad$/.test(process.argv[1]) } } }; DocPad.prototype.regenerateTimer = null; DocPad.prototype.getConfig = function() { return this.config || {}; }; DocPad.prototype.getPort = function() { var _ref1, _ref2, _ref3, _ref4; 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; }; function DocPad(instanceConfig, next) { this.server = __bind(this.server, this); this.serverMiddleware500 = __bind(this.serverMiddleware500, this); this.serverMiddleware404 = __bind(this.serverMiddleware404, this); this.serverMiddlewareRouter = __bind(this.serverMiddlewareRouter, this); this.serveDocument = __bind(this.serveDocument, this); this.skeleton = __bind(this.skeleton, this); this.run = __bind(this.run, this); this.watch = __bind(this.watch, this); this.render = __bind(this.render, this); this.generate = __bind(this.generate, this); this.generatePostpare = __bind(this.generatePostpare, this); this.generateRender = __bind(this.generateRender, this); this.generateParse = __bind(this.generateParse, this); this.generatePrepare = __bind(this.generatePrepare, this); this.action = __bind(this.action, this); this.ensureFileOrDocument = __bind(this.ensureFileOrDocument, this); this.ensureDocument = __bind(this.ensureDocument, this); this.ensureFile = __bind(this.ensureFile, this); this.createDocument = __bind(this.createDocument, this); this.createFile = __bind(this.createFile, this); this.notify = __bind(this.notify, this); this.warn = __bind(this.warn, this); this.error = __bind(this.error, this); this.log = __bind(this.log, this); this.fatal = __bind(this.fatal, this); this.clean = __bind(this.clean, this); this.install = __bind(this.install, this); this.load = __bind(this.load, this); this.setConfig = __bind(this.setConfig, this); this.ready = __bind(this.ready, this); var action, configEventContext, console, docpad, logger, loggers, _ref1, _this = this; _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1]; docpad = this; this.setMaxListeners(0); configEventContext = { docpad: docpad }; this.getEvents().forEach(function(eventName) { return docpad.on(eventName, function(opts, next) { var args, eventHandler, _ref2; eventHandler = (_ref2 = docpad.getConfig().events) != null ? _ref2[eventName] : void 0; if (typeChecker.isFunction(eventHandler)) { args = [opts, next]; return ambi.apply(null, [eventHandler.bind(configEventContext)].concat(__slice.call(args))); } else { return next(); } }); }); this.actionRunnerInstance = new TaskGroup().run().on('complete', function(err) { if (err) { return docpad.error(err); } }); this.errorRunnerInstance = new TaskGroup().run().on('complete', function(err) { var locale; if (err && docpad.getDebugging()) { locale = docpad.getLocale(); return docpad.log('warn', locale.reportError + '\n' + locale.errorFollows, err); } }); this.trackRunnerInstance = new TaskGroup().run().on('complete', function(err) { var locale; if (err && docpad.getDebugging()) { locale = docpad.getLocale(); return docpad.log('warn', locale.trackError + '\n' + locale.errorFollows, err); } }); if ((loggers = instanceConfig.loggers)) { delete instanceConfig.loggers; } else { logger = new (require('caterpillar').Logger)(); (console = logger.pipe(new (require('caterpillar-filter').Filter)).pipe(new (require('caterpillar-human').Human))).pipe(process.stdout); loggers = { logger: logger, console: console }; } safefs.unlink(this.debugLogPath, function() {}); this.setLoggers(loggers); this.setLogLevel(6); this.on('log', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.log.apply(this, args); }); if (canihaz == null) { canihaz = require('canihaz')({ installation: docpad.corePath, location: docpad.packagePath, key: 'lazyDependencies' }); } this.slowPlugins = {}; this.loadedPlugins = {}; this.exchange = {}; this.pluginsTemplateData = {}; this.instanceConfig = {}; this.collections = {}; this.blocks = {}; this.filesByUrl = {}; this.filesBySelector = {}; this.filesByOutPath = {}; this.database = new FilesCollection().on('remove', function(model, options) { var outPath, url, _i, _len, _ref2; if (model.get('write') === false) { return; } _ref2 = model.get('urls') || []; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { url = _ref2[_i]; delete docpad.filesByUrl[url]; } outPath = model.get('outPath'); if (outPath) { return _this.database.findAll({ outPath: outPath }).each(function(model) { return model.set({ 'mtime': new Date() }); }); } }).on('change:urls', function(model, urls, options) { var url, _i, _j, _len, _len1, _ref2, _results; if (urls == null) { urls = []; } if (model.get('write') === false) { return; } _ref2 = model.previous('urls') || []; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { url = _ref2[_i]; delete docpad.filesByUrl[url]; } _results = []; for (_j = 0, _len1 = urls.length; _j < _len1; _j++) { url = urls[_j]; _results.push(docpad.filesByUrl[url] = model.cid); } return _results; }).on('change:outPath', function(model, outPath, options) { var existingModel, existingModelId, existingModelPath, message, modelPath, previousModelId, previousModels, previousOutPath, _base, _ref2; if (model.get('write') === false) { return; } previousOutPath = model.previous('outPath'); if (previousOutPath) { previousModels = _this.database.findAll({ outPath: previousOutPath }); previousModels.each(function(model) { return model.set({ 'mtime': new Date() }); }); previousModelId = _this.filesByOutPath[previousOutPath]; if (previousModelId === model.id) { if (previousModels.length) { _this.filesByOutPath[previousOutPath] = previousModelId; } else { delete _this.filesByOutPath[previousOutPath]; } } } existingModelId = (_ref2 = (_base = _this.filesByOutPath)[outPath]) != null ? _ref2 : _base[outPath] = model.id; if (existingModelId !== model.id) { modelPath = model.get('fullPath'); existingModel = _this.database.get(existingModelId); existingModelPath = existingModel.get('fullPath'); message = util.format(docpad.getLocale().outPathConflict, outPath, modelPath, existingModelPath); return docpad.warn(message); } }); this.locales = extendr.dereference(this.locales); this.userConfig = extendr.dereference(this.userConfig); this.initialConfig = extendr.dereference(this.initialConfig); if (instanceConfig.action != null) { action = instanceConfig.action; } else { action = 'load ready'; } if (action) { this.action(action, instanceConfig, function(err) { if (err) { return docpad.fatal(err); } return typeof next === "function" ? next(null, docpad) : void 0; }); } else { if (typeof next === "function") { next(null, docpad); } } this; } DocPad.prototype.isIgnoredPath = function(path, opts) { if (opts == null) { opts = {}; } opts = extendr.extend({ ignorePaths: this.config.ignorePaths, ignoreHiddenFiles: this.config.ignoreHiddenFiles, ignoreCommonPatterns: this.config.ignoreCommonPatterns, ignoreCustomPatterns: this.config.ignoreCustomPatterns }, opts); return balUtil.isIgnoredPath(path, opts); }; DocPad.prototype.scandir = function(opts) { if (opts == null) { opts = {}; } opts = extendr.extend({ ignorePaths: this.config.ignorePaths, ignoreHiddenFiles: this.config.ignoreHiddenFiles, ignoreCommonPatterns: this.config.ignoreCommonPatterns, ignoreCustomPatterns: this.config.ignoreCustomPatterns }, opts); return balUtil.scandir(opts); }; DocPad.prototype.watchdir = function(opts) { if (opts == null) { opts = {}; } opts = extendr.extend({ ignorePaths: this.config.ignorePaths, ignoreHiddenFiles: this.config.ignoreHiddenFiles, ignoreCommonPatterns: this.config.ignoreCommonPatterns, ignoreCustomPatterns: this.config.ignoreCustomPatterns }, opts, this.config.watchOptions); return require('watchr').watch(opts); }; DocPad.prototype.ready = function(opts, next) { var config, docpad, instanceConfig, locale, mixpanelInstance, pluginName, pluginsList, tasks, _ref1, _this = this; _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1]; docpad = this; config = this.getConfig(); locale = this.getLocale(); mixpanelInstance = this.getMixpanelInstance(); this.DocumentModel.prototype.defaults.renderSingleExtensions = config.renderSingleExtensions; this.compareVersion(); if (this.getDebugging()) { pluginsList = ((function() { var _i, _len, _ref2, _results; _ref2 = Object.keys(this.loadedPlugins).sort(); _results = []; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { pluginName = _ref2[_i]; _results.push("" + pluginName + " v" + this.loadedPlugins[pluginName].version); } return _results; }).call(this)).join(', '); } else { pluginsList = Object.keys(this.loadedPlugins).sort().join(', '); } this.log('info', util.format(locale.welcome, "v" + (this.getVersion()))); this.log('info', util.format(locale.welcomePlugins, pluginsList)); this.log('info', util.format(locale.welcomeEnvironment, this.getEnvironment())); tasks = new TaskGroup().once('complete', function(err) { if (err) { return docpad.error(err); } return typeof next === "function" ? next(null, docpad) : void 0; }); tasks.addTask(function(complete) { if (!config.welcome) { return complete(); } return _this.emitSync('welcome', { docpad: docpad }, complete); }); tasks.addTask(function(complete) { if (!mixpanelInstance || _this.userConfig.username) { return complete(); } return require('getmac').getMac(function(err, macAddress) { var macAddressHash, _base, _base1, _ref2, _ref3; if (err || !macAddress) { return complete(); } try { macAddressHash = require('crypto').createHmac('sha1', config.hashKey).update(macAddress).digest('hex'); } catch (_error) { err = _error; if (err) { return complete(); } } if (macAddressHash) { if ((_ref2 = (_base = _this.userConfig).name) == null) { _base.name = "MAC " + macAddressHash; } if ((_ref3 = (_base1 = _this.userConfig).username) == null) { _base1.username = macAddressHash; } } return complete(); }); }); tasks.addTask(function() { var lastLogin, userData; if (!mixpanelInstance || !_this.userConfig.username) { return; } lastLogin = new Date(); userData = { $email: _this.userConfig.email, $name: _this.userConfig.name, $last_login: lastLogin, $country_code: balUtil.getCountryCode(), languageCode: balUtil.getLanguageCode(), version: _this.getVersion(), platform: _this.getProcessPlatform(), nodeVersion: _this.getProcessVersion() }; if (_this.userConfig.identified !== true) { mixpanelInstance.people.set(_this.userConfig.username, extendr.extend(userData, { $created: lastLogin, $username: _this.userConfig.username })); return _this.updateUserConfig({ identified: true }); } else { return mixpanelInstance.people.set(_this.userConfig.username, userData); } }); tasks.addTask(function(complete) { return _this.emitSync('docpadReady', { docpad: docpad }, complete); }); tasks.run(); return this; }; DocPad.prototype.mergeConfigurations = function(configPackages, configsToMerge) { var configPackage, env, envConfig, envs, _i, _j, _len, _len1, _ref1; envs = this.getEnvironments(); for (_i = 0, _len = configPackages.length; _i < _len; _i++) { configPackage = configPackages[_i]; if (!configPackage) { continue; } configsToMerge.push(configPackage); for (_j = 0, _len1 = envs.length; _j < _len1; _j++) { env = envs[_j]; envConfig = (_ref1 = configPackage.environments) != null ? _ref1[env] : void 0; if (envConfig) { configsToMerge.push(envConfig); } } } extendr.safeDeepExtendPlainObjects.apply(extendr, configsToMerge); return this; }; DocPad.prototype.setInstanceConfig = function(instanceConfig) { if (instanceConfig) { extendr.safeDeepExtendPlainObjects(this.instanceConfig, instanceConfig); if (this.config) { extendr.safeDeepExtendPlainObjects(this.config, instanceConfig); } } return this; }; DocPad.prototype.setConfig = function(instanceConfig, next) { var configPackages, configsToMerge, docpad, key, postTasks, type, typePath, typePaths, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2, _ref3, _this = this; _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1]; docpad = this; if (instanceConfig) { this.setInstanceConfig(instanceConfig); } this.config.env = this.instanceConfig.env || this.websiteConfig.env || this.initialConfig.env || process.env.NODE_ENV; configPackages = [this.initialConfig, this.userConfig, this.websiteConfig, this.instanceConfig]; configsToMerge = [this.config]; docpad.mergeConfigurations(configPackages, configsToMerge); if (this.config.server) { this.setServer(this.config.server); } this.setLogLevel(this.config.logLevel); this.config.rootPath = pathUtil.resolve(this.config.rootPath); this.config.outPath = pathUtil.resolve(this.config.rootPath, this.config.outPath); this.config.srcPath = pathUtil.resolve(this.config.rootPath, this.config.srcPath); _ref2 = ['documents', 'files', 'layouts']; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { type = _ref2[_i]; typePaths = this.config[type + 'Paths']; for (key = _j = 0, _len1 = typePaths.length; _j < _len1; key = ++_j) { typePath = typePaths[key]; typePaths[key] = pathUtil.resolve(this.config.srcPath, typePath); } } _ref3 = ['plugins']; for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) { type = _ref3[_k]; typePaths = this.config[type + 'Paths']; for (key = _l = 0, _len3 = typePaths.length; _l < _len3; key = ++_l) { typePath = typePaths[key]; typePaths[key] = pathUtil.resolve(this.config.rootPath, typePath); } } process.removeListener('uncaughtException', this.error); if (this.config.catchExceptions) { process.setMaxListeners(0); process.on('uncaughtException', this.error); } if (this.regenerateTimer) { clearInterval(this.regenerateTimer); this.regenerateTimer = null; } if (this.config.regenerateEvery) { this.regenerateTimer = setInterval(function() { docpad.log('info', locale.renderInterval); return docpad.action('generate'); }, this.config.regenerateEvery); } postTasks = new TaskGroup().once('complete', function(err) { return next(err, _this.config); }); postTasks.addTask(function(complete) { if (!_this.config.detectEncoding) { return complete(); } return canihaz('iconv', complete); }); postTasks.addTask(function(complete) { return _this.loadPlugins(complete); }); postTasks.addTask(function(complete) { return _this.extendCollections(complete); }); postTasks.addTask(function(complete) { return _this.emitSync('extendTemplateData', { templateData: _this.pluginsTemplateData }, complete); }); postTasks.addTask(function(complete) { return _this.emitSync('docpadLoaded', {}, complete); }); postTasks.run(); return this; }; DocPad.prototype.load = function(instanceConfig, next) { var docpad, locale, preTasks, _ref1, _this = this; _ref1 = balUtil.extractOptsAndCallback(instanceConfig, next), instanceConfig = _ref1[0], next = _ref1[1]; docpad = this; locale = this.getLocale(); instanceConfig || (instanceConfig = {}); this.websitePackageConfig = {}; this.websiteConfig = {}; this.config = {}; this.setInstanceConfig(instanceConfig); preTasks = new TaskGroup().once('complete', function(err) { if (err) { return next(err); } return _this.setConfig(next); }); preTasks.addTask(function(complete) { return balUtil.getHomePath(function(err, homePath) { var dropboxPath; if (err) { return complete(err); } dropboxPath = pathUtil.join(homePath, 'Dropbox'); return safefs.exists(dropboxPath, function(dropboxPathExists) { var userConfigDirPath; userConfigDirPath = dropboxPathExists ? dropboxPath : homePath; _this.userConfigPath = pathUtil.join(userConfigDirPath, _this.userConfigPath); return complete(); }); }); }); preTasks.addTask(function(complete) { return _this.loadConfigPath(_this.userConfigPath, function(err, data) { if (err) { return complete(err); } extendr.extend(_this.userConfig, data || {}); return complete(); }); }); preTasks.addTask(function(complete) { return _this.loadConfigPath(_this.packagePath, function(err, data) { var _ref2; if (err) { return complete(err); } data || (data = {}); _this.version = data.version; if ((_ref2 = _this.getAirbrakeInstance()) != null) { _ref2.appVersion = data.version; } return complete(); }); }); preTasks.addTask(function(complete) { var rootPath, websitePackagePath; rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.initialConfig.rootPath); websitePackagePath = pathUtil.resolve(rootPath, _this.instanceConfig.packagePath || _this.initialConfig.packagePath); return _this.loadConfigPath(websitePackagePath, function(err, data) { if (err) { return complete(err); } data || (data = {}); _this.websitePackageConfig = data; return complete(); }); }); preTasks.addTask(function(complete) { var envPath, rootPath; rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.websitePackageConfig.rootPath || _this.initialConfig.rootPath); envPath = pathUtil.join(rootPath, '.env'); return safefs.exists(envPath, function(exists) { if (!exists) { return complete(); } return safefs.readFile(envPath, function(err, data) { var key, line, lines, match, result, value, _i, _len; if (err) { return complete(err); } result = data.toString(); lines = result.split('\n'); for (_i = 0, _len = lines.length; _i < _len; _i++) { line = lines[_i]; match = line.match(/^([^=]+?)=(.*)/); if (match) { key = match[1]; value = match[2]; process.env[key] = value; } } return complete(); }); }); }); preTasks.addTask(function(complete) { var configPath, configPaths, index, rootPath, _i, _len; rootPath = pathUtil.resolve(_this.instanceConfig.rootPath || _this.initialConfig.rootPath); configPaths = _this.instanceConfig.configPaths || _this.initialConfig.configPaths; for (index = _i = 0, _len = configPaths.length; _i < _len; index = ++_i) { configPath = configPaths[index]; configPaths[index] = pathUtil.resolve(rootPath, configPath); } return _this.loadConfigPaths(configPaths, function(err, data) { if (err) { return complete(err); } data || (data = {}); extendr.extend(_this.websiteConfig, data); return complete(); }); }); preTasks.run(); return this; }; DocPad.prototype.install = function(opts, next) { var docpad, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; this.initNodeModules({ path: this.config.rootPath, output: true, next: function(err) { if (err) { return next(err); } return docpad.load(function(err) { return next(err); }); } }); return this; }; DocPad.prototype.clean = function(opts, next) { var docpad, locale, outPath, rootPath, _ref1, _ref2; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; locale = this.getLocale(); _ref2 = this.config, rootPath = _ref2.rootPath, outPath = _ref2.outPath; docpad.log('debug', locale.renderCleaning); docpad.resetCollections(function(err) { if (err) { return next(err); } if (rootPath.indexOf(outPath) !== -1) { return next(); } else { return balUtil.rmdirDeep(outPath, function(err, list, tree) { if (!err) { docpad.log('debug', locale.renderCleaned); } return next(); }); } }); return this; }; DocPad.prototype.updateUserConfig = function(data, next) { var docpad, userConfigPath, _ref1; if (data == null) { data = {}; } _ref1 = balUtil.extractOptsAndCallback(data, next), data = _ref1[0], next = _ref1[1]; docpad = this; userConfigPath = this.userConfigPath; if (data) { extendr.extend(this.userConfig, data); } CSON.stringify(this.userConfig, function(err, userConfigString) { if (err) { return typeof next === "function" ? next(err) : void 0; } return safefs.writeFile(userConfigPath, userConfigString, 'utf8', function(err) { return typeof next === "function" ? next(err) : void 0; }); }); return this; }; DocPad.prototype.loadConfigUrl = function(configUrl, next) { var locale; locale = this.getLocale(); this.log('debug', util.format(locale.loadingConfigUrl, configUrl)); balUtil.readPath(configUrl, function(err, body) { if (err) { return next(err); } return CSON.parse(body, next); }); return this; }; DocPad.prototype.loadConfigPath = function(configPath, next) { var locale; locale = this.getLocale(); this.log('debug', util.format(locale.loadingConfigPath, configPath)); safefs.exists(configPath, function(exists) { if (!exists) { return next(null, null); } return CSON.parseFile(configPath, next); }); return this; }; DocPad.prototype.loadConfigPaths = function(configPaths, next) { var docpad, result, tasks; docpad = this; result = null; if (!typeChecker.isArray(configPaths)) { configPaths = [configPaths]; } tasks = new TaskGroup().once('complete', function(err) { return next(err, result); }); configPaths.forEach(function(configPath) { return tasks.addTask(function(complete) { if (result) { return complete(); } return docpad.loadConfigPath(configPath, function(err, config) { if (err) { return complete(err); } if (config) { result = config; tasks.clear(); return complete(); } else { return complete(); } }); }); }); tasks.run(); return this; }; DocPad.prototype.extendCollections = function(next) { var config, database, docpad, locale, tasks; docpad = this; config = this.config; locale = this.getLocale(); database = this.getDatabase(); this.setCollections({ documents: database.createLiveChildCollection().setQuery('isDocument', { $or: { isDocument: true, fullPath: { $startsWith: config.documentsPaths } } }).on('add', function(model) { docpad.log('debug', util.format(locale.addingDocument, model.attributes.fullPath)); return model.setDefaults({ isDocument: true, render: true, write: true }); }), files: database.createLiveChildCollection().setQuery('isFile', { $or: { isFile: true, fullPath: { $startsWith: config.filesPaths } } }).on('add', function(model) { docpad.log('debug', util.format(locale.addingFile, model.attributes.fullPath)); return model.setDefaults({ isFile: true, render: false, write: true }); }), layouts: database.createLiveChildCollection().setQuery('isLayout', { $or: { isLayout: true, fullPath: { $startsWith: config.layoutsPaths } } }).on('add', function(model) { docpad.log('debug', util.format(locale.addingLayout, model.attributes.fullPath)); return model.setDefaults({ isLayout: true, render: false, write: false }); }), html: database.createLiveChildCollection().setQuery('isHTML', { $or: { isDocument: true, isFile: true }, outExtension: 'html' }).on('add', function(model) { return docpad.log('debug', util.format(locale.addingHtml, model.attributes.fullPath)); }), stylesheet: database.createLiveChildCollection().setQuery('isStylesheet', { $or: { isDocument: true, isFile: true }, outExtension: { $in: ['css', 'scss', 'sass', 'styl', 'stylus', 'less'] } }).on('add', function(model) { docpad.log('debug', util.format(locale.addingStylesheet, model.attributes.fullPath)); return model.setDefaults({ referencesOthers: true }); }) }); this.setBlocks({ meta: new MetaCollection(), scripts: new ScriptsCollection(), styles: new StylesCollection() }); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { docpad.error(err); } return docpad.emitSync('extendCollections', {}, next); }); eachr(this.config.collections || {}, function(fn, name) { return tasks.addTask(function(complete) { var collection; if (fn.length === 2) { return fn.call(docpad, database, function(err, collection) { if (err) { docpad.error(err); } if (collection) { collection.live(true); } docpad.setCollection(name, collection); return complete(); }); } else { collection = fn.call(docpad, database); if (collection) { collection.live(true); } docpad.setCollection(name, collection); return complete(); } }); }); tasks.run(); return this; }; DocPad.prototype.resetCollections = function(next) { var database; database = this.getDatabase(); this.databaseCache = new FilesCollection(database.models); database.reset([]); this.getBlock('meta').reset([]).add([""]); this.getBlock('scripts').reset([]); this.getBlock('styles').reset([]); this.filesByUrl = {}; this.filesBySelector = {}; this.filesByOutPath = {}; this.emitSync('populateCollections', {}, next); return this; }; DocPad.prototype.initGitRepo = function(opts) { balUtil.initGitRepo(opts); return this; }; DocPad.prototype.initNodeModules = function(opts) { var _ref1, _ref2; if (opts == null) { opts = {}; } if ((_ref1 = opts.force) == null) { opts.force = this.config.force; } if ((_ref2 = opts.output) == null) { opts.output = this.getDebugging(); } balUtil.initNodeModules(opts); return this; }; DocPad.prototype.setLogLevel = function(level) { var loggers, _ref1; this.getLogger().setConfig({ level: level }); if (level === 7) { loggers = this.getLoggers(); if ((_ref1 = loggers.debug) == null) { loggers.debug = loggers.logger.pipe(new (require('caterpillar-human').Human)({ color: false })).pipe(require('fs').createWriteStream(this.debugLogPath)); } } return this; }; DocPad.prototype.getLogLevel = function() { return this.config.logLevel; }; DocPad.prototype.getDebugging = function() { return this.getLogLevel() === 7; }; DocPad.prototype.fatal = function(err) { var config, docpad; docpad = this; config = this.getConfig(); if (!err) { return this; } this.error(err, 'err', function() { if (config.catchExceptions) { return process.exit(-1); } else { throw err; } }); return this; }; DocPad.prototype.log = function() { var args, logger; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; logger = this.getLogger(); logger.log.apply(logger, args); return this; }; DocPad.prototype.error = function(err, type, next) { var airbrake, docpad, locale, _ref1; if (type == null) { type = 'err'; } docpad = this; locale = this.getLocale(); if (!err || err.logged) { if (typeof next === "function") { next(); } return this; } err.logged = true; if (err.message == null) { err = new Error(err); } err.logged = true; docpad.log(type, locale.errorOccured, '\n' + ((_ref1 = err.stack) != null ? _ref1 : err.message)); docpad.notify(err.message, { title: locale.errorOccured }); airbrake = this.getAirbrakeInstance(); if (airbrake) { err.params = { docpadVersion: this.version, docpadConfig: this.config }; this.getErrorRunner().addTask(function(complete) { return airbrake.notify(err, function(airbrakeErr, airbrakeUrl) { if (airbrakeErr) { return complete(airbrakeErr); } else { console.log(util.format(locale.errorLoggedTo, airbrakeUrl)); return complete(); } }); }); } else { if (typeof next === "function") { next(); } } return this; }; DocPad.prototype.warn = function(message, err, next) { var docpad, locale; docpad = this; locale = this.getLocale(); docpad.log('warn', message); if (err) { docpad.error(err, 'warn', next); } docpad.notify(message, { title: locale.warnOccured }); return this; }; DocPad.prototype.notify = function(message, opts) { var docpad, err, growl; docpad = this; growl = this.getGrowlInstance(); if (growl) { try { growl(message, opts); } catch (_error) { err = _error; } } return this; }; DocPad.prototype.track = function(name, data, next) { var mixpanelInstance, _ref1, _ref2; if (data == null) { data = {}; } mixpanelInstance = this.getMixpanelInstance(); if (mixpanelInstance) { if ((_ref1 = this.userConfig) != null ? _ref1.username : void 0) { data.distinct_id = this.userConfig.username; data.username = this.userConfig.username; } if ((_ref2 = this.websitePackageConfig) != null ? _ref2.name : void 0) { data.websiteName = this.websitePackageConfig.name; } data.version = this.getVersion(); data.platform = this.getProcessPlatform(); data.nodeVersion = this.getProcessVersion(); data.environment = this.getEnvironment(); eachr(this.loadedPlugins, function(value, key) { return data['plugin-' + key] = value.version || true; }); this.getTrackRunner().addTask(function(complete) { return mixpanelInstance.track(name, data, function(err) { if (typeof next === "function") { next(); } return complete(err); }); }); } return this; }; DocPad.prototype.createFile = function(data, options) { var docpad, file; if (data == null) { data = {}; } if (options == null) { options = {}; } docpad = this; options = extendr.extend({ detectEncoding: this.config.detectEncoding, outDirPath: this.config.outPath }, options); file = new FileModel(data, options); file.on('log', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.log.apply(docpad, args); }); file.on('render', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.emitSync.apply(docpad, ['render'].concat(__slice.call(args))); }); return file; }; DocPad.prototype.createDocument = function(data, options) { var docpad, document; if (data == null) { data = {}; } if (options == null) { options = {}; } docpad = this; options = extendr.extend({ detectEncoding: this.config.detectEncoding, outDirPath: this.config.outPath }, options); document = new DocumentModel(data, options); document.on('log', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.log.apply(docpad, args); }); document.on('getLayout', function(opts, next) { var layout; if (opts == null) { opts = {}; } opts.collection = docpad.getCollection('layouts'); layout = docpad.getFileBySelector(opts.selector, opts); return next(null, { layout: layout }); }); document.on('render', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.emitSync.apply(docpad, ['render'].concat(__slice.call(args))); }); document.on('renderDocument', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return docpad.emitSync.apply(docpad, ['renderDocument'].concat(__slice.call(args))); }); return document; }; DocPad.prototype.ensureFile = function(data, options) { var database, result; if (data == null) { data = {}; } if (options == null) { options = {}; } database = this.getDatabase(); result = database.findOne({ fullPath: data.fullPath }); if (!result) { result = this.createFile(data, options); database.add(result); } return result; }; DocPad.prototype.ensureDocument = function(data, options) { var database, result; if (data == null) { data = {}; } if (options == null) { options = {}; } database = this.getDatabase(); result = database.findOne({ fullPath: data.fullPath }); if (!result) { result = this.createDocument(data, options); database.add(result); } return result; }; DocPad.prototype.ensureFileOrDocument = function(data, options) { var config, database, dirPath, docpad, fileFullPath, result, _i, _j, _len, _len1, _ref1, _ref2; if (data == null) { data = {}; } if (options == null) { options = {}; } docpad = this; config = this.getConfig(); database = this.getDatabase(); fileFullPath = data.fullPath || null; result = database.findOne({ fullPath: fileFullPath }); if (!result) { if (fileFullPath) { _ref1 = config.documentsPaths.concat(config.layoutsPaths); for (_i = 0, _len = _ref1.length; _i < _len; _i++) { dirPath = _ref1[_i]; if (fileFullPath.indexOf(dirPath) === 0) { data.relativePath || (data.relativePath = fileFullPath.replace(dirPath, '').replace(/^[\/\\]/, '')); result = this.createDocument(data, options); break; } } if (!result) { _ref2 = config.filesPaths; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { dirPath = _ref2[_j]; if (fileFullPath.indexOf(dirPath) === 0) { data.relativePath || (data.relativePath = fileFullPath.replace(dirPath, '').replace(/^[\/\\]/, '')); result = this.createFile(data, options); break; } } } } if (!result) { result = this.createDocument(data, options); } database.add(result); } return result; }; DocPad.prototype.parseFileDirectory = function(opts, next) { var _ref1; if (opts == null) { opts = {}; } if ((_ref1 = opts.createFunction) == null) { opts.createFunction = this.createFile; } return this.parseDirectory(opts, next); }; DocPad.prototype.parseDocumentDirectory = function(opts, next) { var _ref1; if (opts == null) { opts = {}; } if ((_ref1 = opts.createFunction) == null) { opts.createFunction = this.createDocument; } return this.parseDirectory(opts, next); }; DocPad.prototype.parseDirectory = function(opts, next) { var createFunction, docpad, filesToLoad, locale, path; if (opts == null) { opts = {}; } docpad = this; locale = this.getLocale(); path = opts.path, createFunction = opts.createFunction; filesToLoad = new FilesCollection(); if (!safefs.existsSync(path)) { docpad.log('debug', util.format(locale.renderDirectoryNonexistant, path)); return next(); } docpad.log('debug', util.format(locale.renderDirectoryParsing, path)); this.scandir({ path: path, fileAction: function(fileFullPath, fileRelativePath, nextFile, fileStat) { var data, file, options; data = { fullPath: fileFullPath, relativePath: fileRelativePath }; options = { stat: fileStat }; file = createFunction(data, options); filesToLoad.add(file); return nextFile(); }, next: function(err) { if (err) { return next(err); } docpad.log('debug', util.format(locale.renderDirectoryParsed, path)); return docpad.loadFiles({ collection: filesToLoad }, function(err) { return next(err); }); } }); return this; }; DocPad.prototype.getPlugin = function(pluginName) { return this.loadedPlugins[pluginName]; }; DocPad.prototype.hasPlugins = function() { return typeChecker.isEmptyObject(this.loadedPlugins) === false; }; DocPad.prototype.loadPlugins = function(next) { var docpad, locale, snore, tasks, _this = this; docpad = this; locale = this.getLocale(); this.slowPlugins = {}; snore = balUtil.createSnore(function() { return docpad.log('notice', util.format(locale.pluginsSlow, Object.keys(docpad.slowPlugins).join(', '))); }); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { docpad.slowPlugins = {}; snore.clear(); return next(err); }); (this.config.pluginsPaths || []).forEach(function(pluginsPath) { var exists; exists = safefs.existsSync(pluginsPath); if (exists) { return tasks.addTask(function(complete) { return _this.loadPluginsIn(pluginsPath, complete); }); } }); (this.config.pluginPaths || []).forEach(function(pluginPath) { var exists; exists = safefs.existsSync(pluginPath); if (exists) { return tasks.addTask(function(complete) { return _this.loadPlugin(pluginPath, complete); }); } }); tasks.run(); return this; }; DocPad.prototype.loadedPlugin = function(pluginName, next) { var docpad, loaded; docpad = this; loaded = docpad.loadedPlugins[pluginName] != null; next(null, loaded); return this; }; DocPad.prototype.loadPlugin = function(fileFullPath, _next) { var config, docpad, enabled, loader, locale, next, pluginName; docpad = this; config = this.getConfig(); locale = this.getLocale(); next = function(err) { delete docpad.slowPlugins[pluginName]; return _next(err); }; loader = new PluginLoader({ dirPath: fileFullPath, docpad: this, BasePlugin: BasePlugin }); pluginName = loader.pluginName; enabled = (config.enableUnlistedPlugins && (config.enabledPlugins[pluginName] != null) === false) || config.enabledPlugins[pluginName] === true; if (docpad.loadedPlugins[pluginName] != null) { docpad.loadedPlugins[pluginName].setConfig(); return _next(); } docpad.slowPlugins[pluginName] = true; if (!enabled) { docpad.log('debug', util.format(locale.pluginSkipped, pluginName)); return next(); } else { docpad.log('debug', util.format(locale.pluginLoading, pluginName)); loader.exists(function(err, exists) { if (err || !exists) { return next(err); } return loader.unsupported(function(err, unsupported) { if (err) { return next(err); } if (unsupported) { if (unsupported === 'version' && config.skipUnsupportedPlugins === false) { docpad.log('warn', util.format(locale.pluginContinued, pluginName)); } else { if (unsupported === 'type') { docpad.log('debug', util.format(locale.pluginSkippedDueTo, pluginName, unsupported)); } else { docpad.log('warn', util.format(locale.pluginSkippedDueTo, pluginName, unsupported)); } return next(); } } return loader.load(function(err) { if (err) { return next(err); } return loader.create({}, function(err, pluginInstance) { if (err) { return next(err); } docpad.loadedPlugins[loader.pluginName] = pluginInstance; docpad.log('debug', util.format(locale.pluginLoaded, pluginName)); return next(); }); }); }); }); } return this; }; DocPad.prototype.loadPluginsIn = function(pluginsPath, next) { var docpad, locale; docpad = this; locale = this.getLocale(); docpad.log('debug', util.format(locale.pluginsLoadingFor, pluginsPath)); this.scandir({ path: pluginsPath, fileAction: false, dirAction: function(fileFullPath, fileRelativePath, _nextFile) { var nextFile, pluginName; pluginName = pathUtil.basename(fileFullPath); if (fileFullPath === pluginsPath) { return _nextFile(null, false); } nextFile = function(err, skip) { if (err) { docpad.warn(util.format(locale.pluginFailedToLoad, pluginName, fileFullPath) + '\n' + locale.errorFollows, err); } return _nextFile(null, skip); }; return docpad.loadPlugin(fileFullPath, function(err) { return nextFile(err, true); }); }, next: function(err) { docpad.log('debug', util.format(locale.pluginsLoadedFor, pluginsPath)); return next(err); } }); return this; }; DocPad.prototype.compareVersion = function() { var docpad, locale; if (!this.config.checkVersion) { return this; } docpad = this; locale = this.getLocale(); balUtil.packageCompare({ local: this.packagePath, remote: this.config.latestPackageUrl, newVersionCallback: function(details) { docpad.notify(locale.upgradeNotification); return docpad.log('notice', util.format(locale.upgradeDetails, details.local.version, details.remote.version, details.local.upgradeUrl || details.remote.installUrl || details.remote.homepage)); } }); return this; }; DocPad.prototype.getExchange = function(next) { var exchangeUrl; if (!typeChecker.isEmptyObject(this.exchange)) { return next(null, this.exchange); } exchangeUrl = this.config.exchangeUrl + '?version=' + this.version; this.loadConfigUrl(exchangeUrl, function(err, parsedData) { if (err) { return next(err); } this.exchange = parsedData; return next(null, parsedData); }); return this; }; DocPad.prototype.installSkeleton = function(skeletonModel, destinationPath, next) { var docpad, packagePath, repoConfig; docpad = this; packagePath = pathUtil.join(destinationPath, 'package.json'); repoConfig = { path: destinationPath, url: skeletonModel.get('repo'), branch: skeletonModel.get('branch'), remote: 'skeleton', output: true, next: function(err) { if (err) { return docpad.error(err); } return docpad.initNodeModules({ path: destinationPath, output: true, next: function(err) { if (err) { return docpad.error(err); } return next(); } }); } }; safefs.ensurePath(destinationPath, function(err) { if (err) { return docpad.error(err); } return docpad.initGitRepo(repoConfig); }); return this; }; DocPad.prototype.loadFiles = function(opts, next) { var collection, database, docpad, locale, tasks; if (opts == null) { opts = {}; } docpad = this; locale = this.getLocale(); database = this.getDatabase(); collection = opts.collection; docpad.log('debug', util.format(locale.loadingFiles, collection.length)); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } return docpad.emitSync('loadAfter', { collection: collection }, function(err) { docpad.log('debug', util.format(locale.loadedFiles, collection.length)); return next(); }); }); collection.forEach(function(file) { return tasks.addTask(function(complete) { var fileRelativePath; fileRelativePath = file.get('relativePath'); docpad.log('debug', util.format(locale.loadingFile, fileRelativePath)); return file.load(function(err) { var fileIgnored, fileParse; if (err) { docpad.warn(util.format(locale.loadingFileFailed, fileRelativePath) + "\n" + locale.errorFollows, err); return complete(); } fileIgnored = file.get('ignored'); fileParse = file.get('parse'); if (fileIgnored || ((fileParse != null) && !fileParse)) { docpad.log('info', util.format(locale.loadingFileIgnored, fileRelativePath)); collection.remove(file); return complete(); } else { docpad.log('debug', util.format(locale.loadedFile, fileRelativePath)); } database.add(file); return complete(); }); }); }); docpad.emitSync('loadBefore', { collection: collection }, function(err) { if (err) { return next(err); } return tasks.run(); }); return this; }; DocPad.prototype.contextualizeFiles = function(opts, next) { var collection, docpad, locale, tasks, templateData, _ref1; if (opts == null) { opts = {}; } docpad = this; locale = this.getLocale(); collection = opts.collection, templateData = opts.templateData; docpad.log('debug', util.format(locale.contextualizingFiles, collection.length)); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } return docpad.emitSync('contextualizeAfter', { collection: collection }, function(err) { if (err) { return next(err); } docpad.log('debug', util.format(locale.contextualizedFiles, collection.length)); return next(); }); }); if ((_ref1 = opts.progress) != null) { _ref1.step('contextualizeFiles').total(collection.length); } collection.forEach(function(file, index) { return tasks.addTask(function(complete) { return file.contextualize(function(err) { var _ref2; if ((_ref2 = opts.progress) != null) { _ref2.tick(); } return complete(err); }); }); }); docpad.emitSync('contextualizeBefore', { collection: collection, templateData: templateData }, function(err) { if (err) { return next(err); } return tasks.run(); }); return this; }; DocPad.prototype.renderFiles = function(opts, next) { var collection, docpad, initialCollection, locale, renderCollection, renderFile, renderPasses, subsequentCollection, tasks, templateData, _i, _results, _this = this; if (opts == null) { opts = {}; } docpad = this; locale = this.getLocale(); collection = opts.collection, templateData = opts.templateData, renderPasses = opts.renderPasses; docpad.log('debug', util.format(locale.renderingFiles, collection.length)); tasks = new TaskGroup().once('complete', function(err) { if (err) { return next(err); } return docpad.emitSync('renderAfter', { collection: collection }, function(err) { if (err) { return next(err); } docpad.log('debug', util.format(locale.renderedFiles, collection.length)); return next(); }); }); renderFile = function(fileToRender, next) { var dynamic, relativePath, render; dynamic = fileToRender.get('dynamic'); render = fileToRender.get('render'); relativePath = fileToRender.get('relativePath'); if (dynamic || ((render != null) && !render) || !relativePath || (fileToRender.render != null) === false) { next(); } else { fileToRender.render({ templateData: templateData }, next); } return fileToRender; }; renderCollection = function(collectionToRender, _arg, next) { var renderPass, step, subTasks, _ref1; renderPass = _arg.renderPass; subTasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', next); step = "renderFiles (pass " + renderPass + ")"; if ((_ref1 = opts.progress) != null) { _ref1.step(step).total(collectionToRender.length); } collectionToRender.forEach(function(file) { return subTasks.addTask(function(complete) { return renderFile(file, function(err) { var _ref2; if ((_ref2 = opts.progress) != null) { _ref2.tick(); } return complete(err); }); }); }); subTasks.run(); return collectionToRender; }; initialCollection = collection.findAll({ 'referencesOthers': false }); subsequentCollection = null; tasks.addTask(function(complete) { return renderCollection(initialCollection, { renderPass: 1 }, function(err) { if (err) { return complete(err); } subsequentCollection = collection.findAll({ 'referencesOthers': true }); return renderCollection(subsequentCollection, { renderPass: 2 }, complete); }); }); if (renderPasses > 1) { (function() { _results = []; for (var _i = 3; 3 <= renderPasses ? _i <= renderPasses : _i >= renderPasses; 3 <= renderPasses ? _i++ : _i--){ _results.push(_i); } return _results; }).apply(this).forEach(function(renderPass) { return tasks.addTask(function(complete) { return renderCollection(subsequentCollection, { renderPass: renderPass }, complete); }); }); } docpad.emitSync('renderBefore', { collection: collection, templateData: templateData }, function(err) { if (err) { return next(err); } return tasks.run(); }); return this; }; DocPad.prototype.writeFiles = function(opts, next) { var collection, docpad, locale, tasks, templateData, _ref1, _this = this; if (opts == null) { opts = {}; } docpad = this; locale = this.getLocale(); collection = opts.collection, templateData = opts.templateData; docpad.log('debug', util.format(locale.writingFiles, collection.length)); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } return docpad.emitSync('writeAfter', { collection: collection }, function(err) { if (err) { return next(err); } docpad.log('debug', util.format(locale.wroteFiles, collection.length)); return next(); }); }); if ((_ref1 = opts.progress) != null) { _ref1.step('writeFiles').total(collection.length); } collection.forEach(function(file, index) { return tasks.addTask(function(complete) { var dynamic, err, finish, relativePath, write; dynamic = file.get('dynamic'); write = file.get('write'); relativePath = file.get('relativePath'); finish = function(err) { var _ref2; if ((_ref2 = opts.progress) != null) { _ref2.tick(); } return complete(err); }; if (dynamic || ((write != null) && !write) || !relativePath) { return finish(); } else if (file.writeRendered != null) { return file.writeRendered(finish); } else if (file.write != null) { return file.write(finish); } else { err = new Error(locale.unknownModelInCollection); return finish(err); } }); }); docpad.emitSync('writeBefore', { collection: collection, templateData: templateData }, function(err) { if (err) { return next(err); } return tasks.run(); }); return this; }; DocPad.prototype.action = function(action, opts, next) { var actions, docpad, forward, locale, runner, tasks, _ref1, _this = this; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; runner = this.getActionRunner(); locale = this.getLocale(); if (typeChecker.isArray(action)) { actions = action; } else { actions = action.split(/[,\s]+/g); } actions = _.uniq(_.compact(actions)); if (actions.length === 1) { action = actions[0]; } else { tasks = new TaskGroup().once('complete', function(err) { return next(err); }); actions.forEach(function(action) { return tasks.addTask(function(complete) { return docpad.action(action, opts, complete); }); }); tasks.run(); return docpad; } this.log('debug', util.format(locale.actionStart, action)); if (next == null) { next = function(err) { if (err) { return docpad.fatal(err); } }; } forward = function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _this.log('debug', util.format(locale.actionFinished, action)); return process.nextTick(function() { return next.apply(null, args); }); }; runner.addTask(function(complete) { var fn; fn = docpad[action]; if (!fn) { return complete(new Error(util.format(locale.actionNonexistant, action))); } docpad.track(action); return fn(opts, function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; forward.apply(null, args); return complete(); }); }); return this; }; DocPad.prototype.generatePrepare = function(opts, next) { var config, docpad, locale, tasks, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; config = this.getConfig(); locale = this.getLocale(); docpad.generating = true; docpad.log('info', locale.renderGenerating); docpad.notify((new Date()).toLocaleTimeString(), { title: locale.renderGeneratingNotification }); tasks = new TaskGroup().once('complete', next); if (opts.reset === true) { if (!docpad.hasPlugins()) { docpad.log('warn', locale.renderNoPlugins); } tasks.addTask(function(complete) { return safefs.exists(config.srcPath, function(exists) { var err; if (exists === false) { err = new Error(locale.renderNonexistant); return complete(err); } else { return complete(); } }); }); tasks.addTask(function(complete) { return docpad.resetCollections(complete); }); } tasks.addTask(function(complete) { return docpad.emitSync('generateBefore', { reset: opts.reset, server: docpad.getServer() }, complete); }); tasks.run(); return this; }; DocPad.prototype.generateParse = function(opts, next) { var config, database, docpad, locale, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; database = this.getDatabase(); config = this.getConfig(); locale = this.getLocale(); this.emitSync('parseBefore', {}, function(err) { var tasks; if (err) { return next(err); } docpad.log('debug', locale.renderParsing); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', function(err) { if (err) { return next(err); } return docpad.emitSync('parseAfter', {}, function(err) { if (err) { return next(err); } docpad.log('debug', locale.renderParsed); return next(err); }); }); config.documentsPaths.forEach(function(documentsPath) { return tasks.addTask(function(complete) { return docpad.parseDocumentDirectory({ path: documentsPath, collection: database }, complete); }); }); config.filesPaths.forEach(function(filesPath) { return tasks.addTask(function(complete) { return docpad.parseFileDirectory({ path: filesPath, collection: database }, complete); }); }); config.layoutsPaths.forEach(function(layoutsPath) { return tasks.addTask(function(complete) { return docpad.parseDocumentDirectory({ path: layoutsPath, collection: database }, complete); }); }); return tasks.run(); }); return this; }; DocPad.prototype.generateRender = function(opts, next) { var docpad, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; opts.templateData || (opts.templateData = this.getTemplateData()); opts.collection || (opts.collection = this.getDatabase()); opts.renderPasses || (opts.renderPasses = this.getConfig().renderPasses); balUtil.flow({ object: docpad, action: 'contextualizeFiles renderFiles writeFiles', args: [opts], next: function(err) { return next(err); } }); return this; }; DocPad.prototype.generatePostpare = function(opts, next) { var collection, database, docpad, locale, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; locale = this.getLocale(); database = this.getDatabase(); collection = opts.collection || database; docpad.generating = false; docpad.generateEnded = new Date(); docpad.databaseCache = null; docpad.emitSync('generateAfter', { server: docpad.getServer() }, function(err) { var howMany, seconds, _ref2; if (err) { return next(err); } seconds = (docpad.generateEnded - docpad.generateStarted) / 1000; howMany = collection === database ? "all " + collection.length : collection.length; if ((_ref2 = opts.progress) != null) { _ref2.finish(); } docpad.log('info', util.format(locale.renderGenerated, howMany, seconds)); docpad.notify((new Date()).toLocaleTimeString(), { title: locale.renderGeneratedNotification }); return next(); }); return this; }; DocPad.prototype.generateStarted = null; DocPad.prototype.generateEnded = null; DocPad.prototype.generating = false; DocPad.prototype.generate = function(opts, next) { var config, docpad, finish, locale, _ref1, _ref2, _ref3, _ref4; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; config = this.getConfig(); locale = this.getLocale(); if ((_ref2 = opts.reset) == null) { opts.reset = true; } if (((_ref3 = opts.collection) != null ? _ref3.length : void 0) === 0) { return next(); } if (config.prompts && this.getLogLevel() === 6) { if ((_ref4 = opts.progress) == null) { opts.progress = require('progressbar').create(); } docpad.getLoggers().console.unpipe(process.stdout); } finish = function(err) { if (opts.progress) { opts.progress.finish(); opts.progress = null; docpad.getLoggers().console.pipe(process.stdout); } return next(err); }; if ((opts.collection != null) === false && opts.reset === false) { docpad.generatePrepare(opts, function(err) { var database, filesToReload; if (err) { return finish(err); } database = docpad.getDatabase(); filesToReload = opts.filesToReload || new FilesCollection(); filesToReload.add(database.findAll({ mtime: { $gte: docpad.generateStarted } }).models); docpad.generateStarted = new Date(); return docpad.loadFiles({ collection: filesToReload }, function(err) { var allStandalone, filesToRender; if (err) { return finish(err); } filesToRender = opts.filesToRender || new FilesCollection(); filesToRender.on('add', function(fileToRender) { if (fileToRender.get('isLayout')) { return filesToRender.add(database.findAll({ layoutId: fileToRender.id }).models); } }); allStandalone = true; filesToReload.forEach(function(fileToReload) { if (fileToReload.get('standalone') !== true) { allStandalone = false; return false; } }); if (allStandalone === false) { filesToRender.add(database.findAll({ referencesOthers: true }).models); } filesToRender.add(filesToReload.models); return docpad.generateRender({ collection: filesToRender }, function(err) { if (err) { return finish(err); } return docpad.generatePostpare({ collection: filesToRender }, function(err) { return finish(err); }); }); }); }); } else { docpad.generateStarted = new Date(); balUtil.flow({ object: docpad, action: 'generatePrepare generateParse generateRender generatePostpare', args: [opts], next: function(err) { return finish(err); } }); } return this; }; DocPad.prototype.flowDocument = function(document, opts, next) { var _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; balUtil.flow({ object: document, action: opts.action, args: [opts], next: function(err) { return typeof next === "function" ? next(err, document) : void 0; } }); return this; }; DocPad.prototype.loadDocument = function(document, opts, next) { var _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; opts.action || (opts.action = 'load contextualize'); this.flowDocument(document, opts, next); return this; }; DocPad.prototype.loadAndRenderDocument = function(document, opts, next) { var _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; opts.action || (opts.action = 'load contextualize render'); this.flowDocument(document, opts, function(err) { var result; result = document.getOutContent(); return typeof next === "function" ? next(err, result, document) : void 0; }); return this; }; DocPad.prototype.renderDocument = function(document, opts, next) { var _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; document.render(opts, next); return this; }; DocPad.prototype.renderPath = function(path, opts, next) { var attributes, document, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; attributes = extendr.extend({ fullPath: path }, opts.attributes); document = this.ensureDocument(attributes); this.loadAndRenderDocument(document, opts, next); return this; }; DocPad.prototype.renderData = function(content, opts, next) { var attributes, document, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; attributes = extendr.extend({ filename: opts.filename, data: content }, opts.attributes); document = this.createDocument(attributes); this.loadAndRenderDocument(document, opts, next); return this; }; DocPad.prototype.renderText = function(text, opts, next) { var attributes, document, _ref1, _ref2; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; if ((_ref2 = opts.actions) == null) { opts.actions = ['renderExtensions', 'renderDocument']; } attributes = extendr.extend({ filename: opts.filename, data: text, body: text, content: text }, opts.attributes); document = this.createDocument(attributes); balUtil.flow({ object: document, action: 'normalize contextualize render', args: [opts], next: function(err) { var result; result = document.getOutContent(); return next(err, result, document); } }); return this; }; DocPad.prototype.render = function(opts, next) { var err, locale, path, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; locale = this.getLocale(); if (opts.document) { this.renderDocument(opts.document, opts, next); } else if (opts.data) { this.renderData(opts.data, opts, next); } else if (opts.text) { this.renderText(opts.text, opts, next); } else { path = opts.path || opts.fullPath || opts.filename || null; if (path) { this.renderPath(path, opts, next); } else { err = new Error(locale.renderInvalidOptions); return next(err); } } return this; }; DocPad.prototype.watch = function(opts, next) { var changeHandler, closeWatchers, config, database, docpad, locale, performGenerate, queueRegeneration, regenerateTimer, resetWatchers, watchers, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; config = this.getConfig(); locale = this.getLocale(); database = this.getDatabase(); watchers = []; closeWatchers = function() { var watcher, _i, _len; for (_i = 0, _len = watchers.length; _i < _len; _i++) { watcher = watchers[_i]; watcher.close(); watcher = null; } return watchers = []; }; resetWatchers = function(next) { var regeneratePaths, reloadPaths, srcPath, tasks; closeWatchers(); tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', next); reloadPaths = _.union(config.reloadPaths, config.configPaths); tasks.addTask(function(complete) { return docpad.watchdir({ paths: reloadPaths, listeners: { 'log': docpad.log, 'error': docpad.error, 'change': function() { docpad.log('info', util.format(locale.watchReloadChange, new Date().toLocaleTimeString())); return docpad.action('load', function(err) { if (err) { return docpad.fatal(err); } return performGenerate({ reset: true }); }); } }, next: function(err, _watchers) { var watcher, _i, _len; if (err) { docpad.log('warn', "Watching the reload paths has failed:", reloadPaths, err); return complete(); } for (_i = 0, _len = _watchers.length; _i < _len; _i++) { watcher = _watchers[_i]; watchers.push(watcher); } return complete(); } }); }); regeneratePaths = config.regeneratePaths; tasks.addTask(function(complete) { return docpad.watchdir({ paths: regeneratePaths, listeners: { 'log': docpad.log, 'error': docpad.error, 'change': function() { return performGenerate({ reset: true }); } }, next: function(err, _watchers) { var watcher, _i, _len; if (err) { docpad.log('warn', "Watching the regenerate paths has failed:", regeneratePaths, err); return complete(); } for (_i = 0, _len = _watchers.length; _i < _len; _i++) { watcher = _watchers[_i]; watchers.push(watcher); } return complete(); } }); }); srcPath = config.srcPath; tasks.addTask(function(complete) { return docpad.watchdir({ path: srcPath, listeners: { 'log': docpad.log, 'error': docpad.error, 'change': changeHandler }, next: function(err, watcher) { if (err) { docpad.log('warn', "Watching the src path has failed:", srcPath, err); return complete(); } watchers.push(watcher); return complete(); } }); }); return tasks.run(); }; regenerateTimer = null; queueRegeneration = function() { if (regenerateTimer) { clearTimeout(regenerateTimer); regenerateTimer = null; } return regenerateTimer = setTimeout(performGenerate, config.regenerateDelay); }; performGenerate = function(opts) { var _ref2; opts || (opts = {}); if ((_ref2 = opts.reset) == null) { opts.reset = false; } docpad.log(util.format(locale.watchRegenerating, new Date().toLocaleTimeString())); return docpad.action('generate', opts, function(err) { if (err) { docpad.error(err); } return docpad.log(util.format(locale.watchRegenerated, new Date().toLocaleTimeString())); }); }; changeHandler = function(changeType, filePath, fileCurrentStat, filePreviousStat) { var file, isDirectory, isIgnored; docpad.log('debug', util.format(locale.watchChange, new Date().toLocaleTimeString()), changeType, filePath); isIgnored = docpad.isIgnoredPath(filePath); if (isIgnored) { docpad.log('debug', util.format(locale.watchIgnoredChange, new Date().toLocaleTimeString()), filePath); return; } isDirectory = (fileCurrentStat || filePreviousStat).isDirectory(); if (isDirectory) { docpad.log('debug', util.format(locale.watchDirectoryChange, new Date().toLocaleTimeString()), filePath); return; } if (fileCurrentStat != null) { fileCurrentStat.mtime = new Date(); } file = docpad.ensureFileOrDocument({ fullPath: filePath }, { stat: fileCurrentStat }); if (changeType === 'update') { file.setStat(fileCurrentStat); } if (changeType === 'delete') { database.remove(file); return file["delete"](function(err) { if (err) { return docpad.error(err); } return queueRegeneration(); }); } else if (changeType === 'create' || changeType === 'update') { return queueRegeneration(); } }; docpad.log(locale.watchStart); resetWatchers(function(err) { if (err) { return next(err); } docpad.log(locale.watchStarted); return next(); }); return this; }; DocPad.prototype.run = function(opts, next) { var destinationPath, docpad, locale, runDocpad, srcPath, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; srcPath = this.config.srcPath; destinationPath = this.config.rootPath; locale = this.getLocale(); runDocpad = function() { return balUtil.flow({ object: docpad, action: 'server generate watch', args: [opts], next: function(err) { return next(err); } }); }; if (safefs.existsSync(srcPath)) { runDocpad(); } else { safefs.readdir(destinationPath, function(err, files) { if (err) { return next(err); } if (files.length) { docpad.log('warn', "\n" + util.format(locale.skeletonNonexistant, destinationPath)); return next(); } else { return docpad.skeleton(opts, function(err) { if (err) { return next(err); } return runDocpad(); }); } }); } return this; }; DocPad.prototype.skeleton = function(opts, next) { var config, destinationPath, docpad, locale, selectSkeletonCallback, skeletonId, srcPath, useNoSkeleton, useSkeleton, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; config = this.getConfig(); skeletonId = config.skeleton; srcPath = config.srcPath; destinationPath = config.rootPath; selectSkeletonCallback = opts.selectSkeletonCallback || null; locale = this.getLocale(); useSkeleton = function(skeletonModel) { docpad.track('skeleton-use', { skeletonId: skeletonModel.id }); docpad.log('info', util.format(locale.skeletonInstall, skeletonModel.get('name'), destinationPath)); return docpad.installSkeleton(skeletonModel, destinationPath, function(err) { if (err) { return next(err); } return docpad.load(function(err) { if (err) { return next(err); } docpad.log('info', locale.skeletonInstalled); return next(err); }); }); }; useNoSkeleton = function() { docpad.track('skeleton-use', { skeletonId: 'none' }); return safefs.ensurePath(srcPath, function(err) { var tasks; if (err) { return next(err); } tasks = new TaskGroup().setConfig({ concurrency: 0 }).once('complete', next); tasks.addTask(function(complete) { return safefs.ensurePath(pathUtil.join(config.rootPath, 'node_modules'), complete); }); tasks.addTask(function(complete) { var data; data = JSON.stringify({ name: 'no-skeleton.docpad', version: '0.1.0', description: 'New DocPad project without using a skeleton', engines: { node: '0.10', npm: '1.2' }, dependencies: { docpad: '6.x' }, main: 'node_modules/docpad/bin/docpad-server' }, null, '\t'); return safefs.writeFile(pathUtil.join(config.rootPath, 'package.json'), data, complete); }); tasks.addTask(function(complete) { var data; 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"; return safefs.writeFile(pathUtil.join(config.rootPath, 'docpad.coffee'), data, complete); }); tasks.addTask(function(complete) { return safefs.ensurePath(config.documentsPaths[0], complete); }); tasks.addTask(function(complete) { return safefs.ensurePath(config.layoutsPaths[0], complete); }); tasks.addTask(function(complete) { return safefs.ensurePath(config.filesPaths[0], complete); }); return tasks.run(); }); }; safefs.exists(srcPath, function(exists) { if (exists) { docpad.log('warn', locale.skeletonExists); return next(); } docpad.track('skeleton-ask'); if (skeletonId) { return useSkeleton(); } else { return docpad.getSkeletons(function(err, skeletonsCollection) { if (err) { return next(err); } return selectSkeletonCallback(skeletonsCollection, function(err, skeletonModel) { if (err) { return next(err); } if ((skeletonModel != null) === false || skeletonModel.id === 'none') { return useNoSkeleton(); } else { return useSkeleton(skeletonModel); } }); }); } }); return this; }; DocPad.prototype.serveDocument = function(opts, next) { var content, contentType, docpad, document, dynamic, err, req, res, templateData, _ref1; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; document = opts.document, err = opts.err, req = opts.req, res = opts.res; docpad = this; if (!document) { if (opts.statusCode != null) { return res.send(opts.statusCode); } else { return next(); } } contentType = document.get('outContentType') || document.get('contentType'); res.setHeader('Content-Type', contentType); dynamic = document.get('dynamic'); if (dynamic) { templateData = extendr.extend({}, req.templateData || {}, { req: req, err: err }); templateData = docpad.getTemplateData(templateData); document.render({ templateData: templateData }, function(err) { var content; content = document.getOutContent(); if (err) { docpad.error(err); return next(err); } else { if (opts.statusCode != null) { return res.send(opts.statusCode, content); } else { return res.send(content); } } }); } else { content = document.getOutContent(); if (content) { if (opts.statusCode != null) { return res.send(opts.statusCode, content); } else { return res.send(content); } } else { if (opts.statusCode != null) { return res.send(opts.statusCode); } else { return next(); } } } return this; }; DocPad.prototype.serverMiddlewareHeader = function(req, res, next) { var docpad, tools; docpad = this; tools = res.get('X-Powered-By').split(/[,\s]+/g); tools.push("DocPad v" + docpad.version); tools = tools.join(','); res.set('X-Powered-By', tools); next(); return this; }; DocPad.prototype.serverMiddlewareRouter = function(req, res, next) { var cleanUrl, database, docpad, file, url; docpad = this; if (docpad.generateEnded === null) { docpad.once('generateAfter', function() { return docpad.serverMiddlewareRouter(req, res, next); }); return this; } database = docpad.getDatabaseCache(); cleanUrl = req.url.replace(/\?.*/, ''); file = docpad.getFileByUrl(req.url, { collection: database }) || docpad.getFileByUrl(cleanUrl, { collection: database }); if ((file != null) === false) { return next(); } url = file.get('url'); if ((url !== cleanUrl) && (url !== req.url)) { return res.redirect(301, url); } docpad.serveDocument({ document: file, req: req, res: res, next: next }); return this; }; DocPad.prototype.serverMiddleware404 = function(req, res, next) { var database, docpad, document; docpad = this; database = docpad.getDatabaseCache(); if (!database) { return res.send(500); } document = database.findOne({ relativeOutPath: '404.html' }); docpad.serveDocument({ document: document, req: req, res: res, next: next, statusCode: 404 }); return this; }; DocPad.prototype.serverMiddleware500 = function(err, req, res, next) { var database, docpad, document; docpad = this; database = docpad.getDatabaseCache(); if (!database) { return res.send(500); } document = database.findOne({ relativeOutPath: '500.html' }); docpad.serveDocument({ document: document, err: err, req: req, res: res, next: next, statusCode: 500 }); return this; }; DocPad.prototype.server = function(opts, next) { var config, docpad, express, finish, http, locale, port, serverExpress, serverHttp, startServer, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; http = null; express = null; _ref1 = balUtil.extractOptsAndCallback(opts, next), opts = _ref1[0], next = _ref1[1]; docpad = this; config = this.config; locale = this.getLocale(); port = this.getPort(); serverExpress = null; serverHttp = null; if ((_ref2 = opts.middlewareBodyParser) == null) { opts.middlewareBodyParser = (_ref3 = config.middlewareBodyParser) != null ? _ref3 : config.middlewareStandard; } if ((_ref4 = opts.middlewareMethodOverride) == null) { opts.middlewareMethodOverride = (_ref5 = config.middlewareMethodOverride) != null ? _ref5 : config.middlewareStandard; } if ((_ref6 = opts.middlewareExpressRouter) == null) { opts.middlewareExpressRouter = (_ref7 = config.middlewareExpressRouter) != null ? _ref7 : config.middlewareStandard; } if ((_ref8 = opts.middleware404) == null) { opts.middleware404 = config.middleware404; } if ((_ref9 = opts.middleware500) == null) { opts.middleware500 = config.middleware500; } finish = function(err) { if (err) { return next(err); } return docpad.emitSync('serverAfter', { server: serverExpress, serverExpress: serverExpress, serverHttp: serverHttp, express: express }, function(err) { if (err) { return next(err); } return next(); }); }; startServer = function(next) { serverHttp.once('error', function(err) { if (err.message.indexOf('EADDRINUSE') !== -1) { err = new Error(util.format(locale.serverInUse, port)); } return next(err); }); docpad.log('debug', util.format(locale.serverStart, port, config.outPath)); return serverHttp.listen(port, function() { var address, serverHostname, serverLocation, serverPort; address = serverHttp.address(); serverHostname = address.address === '0.0.0.0' ? 'localhost' : address.address; serverPort = address.port; serverLocation = "http://" + serverHostname + ":" + serverPort + "/"; docpad.log('info', util.format(locale.serverStarted, serverLocation, config.outPath)); return next(); }); }; docpad.emitSync('serverBefore', {}, function(err) { var _ref10; if (err) { return finish(err); } _ref10 = docpad.getServer(true), serverExpress = _ref10.serverExpress, serverHttp = _ref10.serverHttp; if (!serverExpress && !serverHttp) { if (http == null) { http = require('http'); } if (express == null) { express = require('express'); } serverExpress = opts.serverExpress || express(); serverHttp = opts.serverHttp || http.createServer(serverExpress); docpad.setServer({ serverExpress: serverExpress, serverHttp: serverHttp }); } if (!config.extendServer) { return startServer(finish); } else { if (express == null) { express = require('express'); } if (opts.middlewareBodyParser !== false) { serverExpress.use(express.bodyParser()); } if (opts.middlewareMethodOverride !== false) { serverExpress.use(express.methodOverride()); } docpad.emitSync('serverExtend', { server: serverExpress, serverExpress: serverExpress, serverHttp: serverHttp, express: express }, function(err) { if (err) { return next(err); } serverExpress.use(docpad.serverMiddlewareHeader); if (opts.middlewareExpressRouter !== false) { serverExpress.use(serverExpress.router); } serverExpress.use(docpad.serverMiddlewareRouter); if (config.maxAge) { serverExpress.use(express["static"](config.outPath, { maxAge: config.maxAge })); } else { serverExpress.use(express["static"](config.outPath)); } if (opts.middleware404 !== false) { serverExpress.use(docpad.serverMiddleware404); } if (opts.middleware500 !== false) { return serverExpress.error(docpad.serverMiddleware500); } }); return startServer(finish); } }); return this; }; return DocPad; })(EventEmitterEnhanced); module.exports = { DocPad: DocPad, queryEngine: queryEngine, Backbone: Backbone, createInstance: function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args); return Object(result) === result ? result : child; })(DocPad, args, function(){}); } };