diff --git a/lib/box/index.js b/lib/box/index.js
index 03e31a365d..9c3703f920 100644
--- a/lib/box/index.js
+++ b/lib/box/index.js
@@ -6,9 +6,8 @@ var _ = require('lodash');
var File = require('./file');
var util = require('hexo-util');
var fs = require('hexo-fs');
-var crypto = require('crypto');
var chalk = require('chalk');
-var through2 = require('through2');
+var ShasumStream = require('./shasum_stream');
var Pattern = util.Pattern;
var escapeRegExp = util.escapeRegExp;
@@ -101,7 +100,11 @@ Box.prototype.process = function(callback){
if (!exist) return;
return self._loadFiles();
}).then(function(files){
- if (files && files.length) return self._process(files);
+ if (!files || !files.length) return;
+
+ return self._process(files).finally(function(){
+ files.length = 0;
+ });
}).nodeify(callback);
};
@@ -110,8 +113,8 @@ Box.prototype.load = Box.prototype.process;
function listDir(path){
return fs.listDir(path).catch(function(err){
// Return an empty array if path does not exist
- if (err.cause.code !== 'ENOENT') throw err;
- return [];
+ if (err.cause.code === 'ENOENT') return [];
+ throw err;
}).map(escapeBackslash);
}
@@ -166,6 +169,8 @@ Box.prototype._loadFiles = function(){
return result;
}).map(function(item){
+ existed.length = 0;
+
switch (item.type){
case 'create':
case 'update':
@@ -179,15 +184,14 @@ Box.prototype._loadFiles = function(){
function getShasum(path){
return new Promise(function(resolve, reject){
- var hash = crypto.createHash('sha1');
- var stream = fs.createReadStream(path);
-
- stream.pipe(through2(function(chunk, enc, callback){
- hash.update(chunk);
- callback();
- }, function(){
- resolve(hash.digest('hex'));
- })).on('error', reject);
+ var src = fs.createReadStream(path);
+ var stream = new ShasumStream();
+
+ src.pipe(stream)
+ .on('error', reject)
+ .on('finish', function(){
+ resolve(stream.getShasum());
+ });
});
}
@@ -246,7 +250,7 @@ Box.prototype._handleDeletedFile = function(path){
if (!cache) return resolve();
ctx.log.debug('Deleted: %s', chalk.magenta(id));
- return cache.remove().then(resolve, reject);
+ cache.remove().then(resolve, reject);
}).thenReturn({
type: 'delete',
path: path
diff --git a/lib/box/shasum_stream.js b/lib/box/shasum_stream.js
new file mode 100644
index 0000000000..976b617507
--- /dev/null
+++ b/lib/box/shasum_stream.js
@@ -0,0 +1,32 @@
+'use strict';
+
+var Stream = require('stream');
+var Transform = Stream.Transform;
+var crypto = require('crypto');
+
+function ShasumStream(options){
+ Transform.call(this, options);
+
+ this._hash = crypto.createHash('sha1');
+ this._shasum = '';
+}
+
+require('util').inherits(ShasumStream, Transform);
+
+ShasumStream.prototype._transform = function(chunk, enc, callback){
+ var buffer = chunk instanceof Buffer ? chunk : new Buffer(chunk, enc);
+
+ this._hash.update(buffer);
+ callback();
+};
+
+ShasumStream.prototype._flush = function(callback){
+ this._shasum = this._hash.digest('hex');
+ callback();
+};
+
+ShasumStream.prototype.getShasum = function(){
+ return this._shasum;
+};
+
+module.exports = ShasumStream;
\ No newline at end of file
diff --git a/lib/hexo/index.js b/lib/hexo/index.js
index 79031a47a7..99ed4c484e 100644
--- a/lib/hexo/index.js
+++ b/lib/hexo/index.js
@@ -244,7 +244,7 @@ Hexo.prototype.load = function(callback){
self.theme.process()
]);
}).then(function(){
- return self._generate();
+ return self._generate({cache: true});
}).nodeify(callback);
};
@@ -252,7 +252,7 @@ Hexo.prototype.watch = function(callback){
var self = this;
function generate(){
- return self._generate({watch: true});
+ return self._generate({cache: false});
}
return loadDatabase(this).then(function(){
@@ -307,7 +307,7 @@ Hexo.prototype._generate = function(options){
Locals.prototype.theme = _.extend({}, config, theme.config, config.theme_config);
Locals.prototype._ = _;
Locals.prototype.layout = 'layout';
- Locals.prototype.cache = !options.watch;
+ Locals.prototype.cache = options.cache;
Locals.prototype.env = this.env;
Locals.prototype.view_dir = pathFn.join(this.theme_dir, 'layout') + sep;
@@ -362,7 +362,7 @@ Hexo.prototype._generate = function(options){
return self.execFilter('template_locals', locals, {context: self})
.then(function(locals){
route.set(path, function(){
- if (cache != null) return cache;
+ if (options.cache && cache != null) return cache;
var view, name;
@@ -387,6 +387,9 @@ Hexo.prototype._generate = function(options){
route.remove(removed[i]);
}
+ routeList.length = 0;
+ newRouteList.length = 0;
+
self.emit('generateAfter');
// Run after_generate filters
diff --git a/lib/plugins/helper/date.js b/lib/plugins/helper/date.js
index 7fa28f5bcf..d69accab75 100644
--- a/lib/plugins/helper/date.js
+++ b/lib/plugins/helper/date.js
@@ -1,37 +1,47 @@
'use strict';
-var moment = require('moment');
+var moment = require('moment-timezone');
var isMoment = moment.isMoment;
+var isDate = require('util').isDate;
+
+function output(date, format, lang, timezone){
+ if (date == null) date = moment();
+ if (!isMoment(date)) date = moment(isDate(date) ? date : new Date(date));
-function output(date, format, lang){
- if (!isMoment(date)) date = moment(date);
if (lang) date = date.locale(lang);
+ if (timezone) date = date.tz(timezone);
return date.format(format);
}
function toISOString(date){
+ if (date == null){
+ return new Date().toISOString();
+ }
+
if (date instanceof Date || isMoment(date)){
return date.toISOString();
- } else {
- return new Date(date).toISOString();
}
+
+ return new Date(date).toISOString();
}
function dateHelper(date, format){
/* jshint validthis: true */
- return output(date, format || this.config.date_format, getLanguage.call(this));
+ var config = this.config;
+ return output(date, format || config.date_format, getLanguage(this), config.timezone);
}
function timeHelper(date, format){
/* jshint validthis: true */
- return output(date, format || this.config.time_format, getLanguage.call(this));
+ var config = this.config;
+ return output(date, format || config.time_format, getLanguage(this), config.timezone);
}
function fullDateHelper(date, format){
/* jshint validthis: true */
if (format){
- return output(date, format, getLanguage.call(this));
+ return output(date, format, getLanguage(this), this.config.timezone);
} else {
return this.date(date) + ' ' + this.time(date);
}
@@ -39,12 +49,12 @@ function fullDateHelper(date, format){
function timeTagHelper(date, format){
/* jshint validthis: true */
- return '';
+ var config = this.config;
+ return '';
}
-function getLanguage(){
- /* jshint validthis: true */
- var lang = this.page.lang || this.page.language || this.config.language;
+function getLanguage(ctx){
+ var lang = ctx.page.lang || ctx.page.language || ctx.config.language;
if (!lang) return;
if (Array.isArray(lang)) lang = lang[0];
diff --git a/test/scripts/helpers/date.js b/test/scripts/helpers/date.js
index ce2de30246..6051973296 100644
--- a/test/scripts/helpers/date.js
+++ b/test/scripts/helpers/date.js
@@ -1,12 +1,22 @@
'use strict';
-var moment = require('moment');
+var moment = require('moment-timezone');
var should = require('chai').should();
+var sinon = require('sinon');
describe('date', function(){
var Hexo = require('../../../lib/hexo');
var hexo = new Hexo();
var dateHelper = require('../../../lib/plugins/helper/date');
+ var clock;
+
+ before(function(){
+ clock = sinon.useFakeTimers(Date.now());
+ });
+
+ after(function(){
+ clock.restore();
+ });
it('date', function(){
var ctx = {
@@ -16,46 +26,51 @@ describe('date', function(){
var date = dateHelper.date.bind(ctx);
+ // now
+ date().should.eql(moment().format(hexo.config.date_format));
+
// moment
- var now = moment();
- date(now).should.eql(now.format(hexo.config.date_format));
- date(now, 'MMM-D-YYYY').should.eql(now.format('MMM-D-YYYY'));
+ date(moment()).should.eql(moment().format(hexo.config.date_format));
+ date(moment(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// date
- now = new Date();
- date(now).should.eql(moment(now).format(hexo.config.date_format));
- date(now, 'MMM-D-YYYY').should.eql(moment(now).format('MMM-D-YYYY'));
+ date(new Date()).should.eql(moment().format(hexo.config.date_format));
+ date(new Date(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// number
- now = Date.now();
- date(now).should.eql(moment(now).format(hexo.config.date_format));
- date(now, 'MMM-D-YYYY').should.eql(moment(now).format('MMM-D-YYYY'));
+ date(Date.now()).should.eql(moment().format(hexo.config.date_format));
+ date(Date.now(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// page.lang
ctx.page.lang = 'zh-tw';
- date(now).should.eql(moment(now).locale('zh-tw').format(hexo.config.date_format));
+ date(Date.now(), 'MMM D YYYY').should.eql(moment().locale('zh-tw').format('MMM D YYYY'));
ctx.page.lang = '';
// config.language
ctx.config.language = 'ja';
- date(now).should.eql(moment(now).locale('ja').format(hexo.config.date_format));
+ date(Date.now(), 'MMM D YYYY').should.eql(moment().locale('ja').format('MMM D YYYY'));
ctx.config.language = '';
+
+ // timezone
+ ctx.config.timezone = 'UTC';
+ date(Date.now(), 'LLL').should.eql(moment().tz('UTC').format('LLL'));
+ ctx.config.timezone = '';
});
it('date_xml', function(){
var dateXML = dateHelper.date_xml;
+ // now
+ dateXML().should.eql(moment().toISOString());
+
// moment
- var now = moment();
- dateXML(now).should.eql(now.toISOString());
+ dateXML(moment()).should.eql(moment().toISOString());
// date
- now = new Date();
- dateXML(now).should.eql(now.toISOString());
+ dateXML(new Date()).should.eql(moment().toISOString());
// number
- now = Date.now();
- dateXML(now).should.eql(new Date(now).toISOString());
+ dateXML(Date.now()).should.eql(moment().toISOString());
});
it('time', function(){
@@ -66,30 +81,35 @@ describe('date', function(){
var time = dateHelper.time.bind(ctx);
+ // now
+ time().should.eql(moment().format(hexo.config.time_format));
+
// moment
- var now = moment();
- time(now).should.eql(now.format(hexo.config.time_format));
- time(now, 'H:mm').should.eql(now.format('H:mm'));
+ time(moment()).should.eql(moment().format(hexo.config.time_format));
+ time(moment(), 'H:mm').should.eql(moment().format('H:mm'));
// date
- now = new Date();
- time(now).should.eql(moment(now).format(hexo.config.time_format));
- time(now, 'H:mm').should.eql(moment(now).format('H:mm'));
+ time(new Date()).should.eql(moment().format(hexo.config.time_format));
+ time(new Date(), 'H:mm').should.eql(moment().format('H:mm'));
// number
- now = Date.now();
- time(now).should.eql(moment(now).format(hexo.config.time_format));
- time(now, 'H:mm').should.eql(moment(now).format('H:mm'));
+ time(Date.now()).should.eql(moment().format(hexo.config.time_format));
+ time(Date.now(), 'H:mm').should.eql(moment().format('H:mm'));
// page.lang
ctx.page.lang = 'zh-tw';
- time(now).should.eql(moment(now).locale('zh-tw').format(hexo.config.time_format));
+ time(Date.now(), 'A H:mm').should.eql(moment().locale('zh-tw').format('A H:mm'));
ctx.page.lang = '';
// config.language
ctx.config.language = 'ja';
- time(now).should.eql(moment(now).locale('ja').format(hexo.config.time_format));
+ time(Date.now(), 'A H:mm').should.eql(moment().locale('ja').format('A H:mm'));
ctx.config.language = '';
+
+ // timezone
+ ctx.config.timezone = 'UTC';
+ time().should.eql(moment().tz('UTC').format(hexo.config.time_format));
+ ctx.config.timezone = '';
});
it('full_date', function(){
@@ -103,30 +123,35 @@ describe('date', function(){
var fullDate = dateHelper.full_date.bind(ctx);
var fullDateFormat = hexo.config.date_format + ' ' + hexo.config.time_format;
+ // now
+ fullDate().should.eql(moment().format(fullDateFormat));
+
// moment
- var now = moment();
- fullDate(now).should.eql(now.format(fullDateFormat));
- fullDate(now, 'MMM-D-YYYY').should.eql(now.format('MMM-D-YYYY'));
+ fullDate(moment()).should.eql(moment().format(fullDateFormat));
+ fullDate(moment(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// date
- now = new Date();
- fullDate(now).should.eql(moment(now).format(fullDateFormat));
- fullDate(now, 'MMM-D-YYYY').should.eql(moment(now).format('MMM-D-YYYY'));
+ fullDate(new Date()).should.eql(moment().format(fullDateFormat));
+ fullDate(new Date(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// number
- now = Date.now();
- fullDate(now).should.eql(moment(now).format(fullDateFormat));
- fullDate(now, 'MMM-D-YYYY').should.eql(moment(now).format('MMM-D-YYYY'));
+ fullDate(Date.now()).should.eql(moment().format(fullDateFormat));
+ fullDate(Date.now(), 'MMM-D-YYYY').should.eql(moment().format('MMM-D-YYYY'));
// page.lang
ctx.page.lang = 'zh-tw';
- fullDate(now).should.eql(moment(now).locale('zh-tw').format(fullDateFormat));
+ fullDate(Date.now(), 'LLL').should.eql(moment().locale('zh-tw').format('LLL'));
ctx.page.lang = '';
// config.language
ctx.config.language = 'ja';
- fullDate(now).should.eql(moment(now).locale('ja').format(fullDateFormat));
+ fullDate(Date.now(), 'LLL').should.eql(moment().locale('ja').format('LLL'));
ctx.config.language = '';
+
+ // timezone
+ ctx.config.timezone = 'UTC';
+ fullDate().should.eql(moment().tz('UTC').format(fullDateFormat));
+ ctx.config.timezone = '';
});
it('time_tag', function(){
@@ -138,29 +163,45 @@ describe('date', function(){
var timeTag = dateHelper.time_tag.bind(ctx);
+ function result(date, format){
+ date = date || new Date();
+ format = format || hexo.config.date_format;
+ return '';
+ }
+
+ function check(date, format){
+ format = format || hexo.config.date_format;
+ timeTag(date, format).should.eql(result(date, format));
+ }
+
+ // now
+ timeTag().should.eql(result());
+
// moment
- var now = moment();
- timeTag(now).should.eql('');
- timeTag(now, 'MMM-D-YYYY').should.eql('');
+ check(moment());
+ check(moment(), 'MMM-D-YYYY');
// date
- now = new Date();
- timeTag(now).should.eql('');
- timeTag(now, 'MMM-D-YYYY').should.eql('');
+ check(new Date());
+ check(new Date(), 'MMM-D-YYYY');
// number
- now = Date.now();
- timeTag(now).should.eql('');
- timeTag(now, 'MMM-D-YYYY').should.eql('');
+ check(Date.now());
+ check(Date.now(), 'MMM-D-YYYY');
// page.lang
ctx.page.lang = 'zh-tw';
- timeTag(now).should.eql('');
+ timeTag(Date.now(), 'LLL').should.eql('');
ctx.page.lang = '';
// config.language
ctx.config.language = 'ja';
- timeTag(now).should.eql('');
+ timeTag(Date.now(), 'LLL').should.eql('');
ctx.config.language = '';
+
+ // timezone
+ ctx.config.timezone = 'UTC';
+ timeTag(Date.now(), 'LLL').should.eql('');
+ ctx.config.timezone = '';
});
});
\ No newline at end of file