Skip to content

Commit

Permalink
Several improvements:
Browse files Browse the repository at this point in the history
- Add hexo.execFilter/execFilterSync as aliases for hexo.extend.filter.exec/execSync
- Add before_generate, after_generate filters
- Move post rendering to before_generate filters
- Render Swig tags in post.render
- Change the output of "hexo list post/page" command
- Parse special date format in source files and fallback to file stats if parsing failed
  • Loading branch information
tommy351 committed Jan 22, 2015
1 parent 8bb634e commit 3ea11a7
Show file tree
Hide file tree
Showing 33 changed files with 620 additions and 342 deletions.
12 changes: 6 additions & 6 deletions lib/box/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var escapeRegExp = util.escapeRegExp;
var join = pathFn.join;
var sep = pathFn.sep;

var patternNoob = new Pattern(function(){
var defaultPattern = new Pattern(function(){
return {};
});

Expand Down Expand Up @@ -85,7 +85,7 @@ function escapeBackslashWindows(path){
Box.prototype.addProcessor = function(pattern, fn){
if (!fn && typeof pattern === 'function'){
fn = pattern;
pattern = patternNoob;
pattern = defaultPattern;
}

if (typeof fn !== 'function') throw new TypeError('fn must be a function');
Expand All @@ -104,7 +104,7 @@ Box.prototype.process = function(callback){
if (!exist) return;
return self._loadFiles();
}).then(function(files){
if (files) return self._process(files);
if (files && files.length) return self._process(files);
}).nodeify(callback);
};

Expand Down Expand Up @@ -219,7 +219,7 @@ Box.prototype._handleUpdatedFile = function(path){
self.statStore[path] = stats;

if (!cache){
ctx.log.info('Added: %s', chalk.magenta(id));
ctx.log.debug('Added: %s', chalk.magenta(id));

return Cache.insert({
_id: id,
Expand All @@ -230,14 +230,14 @@ Box.prototype._handleUpdatedFile = function(path){
path: path
});
} else if (cache.shasum === shasum){
ctx.log.info('Unchanged: %s', chalk.magenta(id));
ctx.log.debug('Unchanged: %s', chalk.magenta(id));

return {
type: 'skip',
path: path
};
} else {
ctx.log.info('Updated: %s', chalk.magenta(id));
ctx.log.debug('Updated: %s', chalk.magenta(id));

cache.shasum = shasum;
cache.modified = stats.mtime;
Expand Down
49 changes: 35 additions & 14 deletions lib/hexo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Hexo.prototype.init = function(){
], function(name){
return require('./' + name)(self);
}).then(function(){
return self.extend.filter.exec('after_init', null, {context: self});
return self.execFilter('after_init', null, {context: self});
}).then(function(){
// Ready to go!
self.emit('ready');
Expand Down Expand Up @@ -263,7 +263,6 @@ Hexo.prototype._generate = function(options){
this._isGenerating = true;

var config = this.config;
var siteLocals = _.clone(this.locals);
var generators = this.extend.generator.list();
var route = this.route;
var keys = Object.keys(generators);
Expand All @@ -272,6 +271,7 @@ Hexo.prototype._generate = function(options){
var log = this.log;
var theme = this.theme;
var newRouteList = [];
var siteLocals = {};

this.emit('generateBefore');

Expand All @@ -284,7 +284,6 @@ Hexo.prototype._generate = function(options){
this.url = config.url + config.root + path;
}

Locals.prototype.site = siteLocals;
Locals.prototype.config = config;
Locals.prototype.theme = _.extend({}, config, theme.config, config.theme_config);
Locals.prototype._ = _;
Expand All @@ -293,18 +292,28 @@ Hexo.prototype._generate = function(options){
Locals.prototype.env = this.env;
Locals.prototype.view_dir = pathFn.join(this.theme_dir, 'layout') + sep;

return Promise.reduce(keys, function(result, key){
var generator = generators[key];
var start = process.hrtime();
// Run before_generate filters
return this.execFilter('before_generate', null, {context: this})
.then(function(){
siteLocals = _.clone(self.locals);
Locals.prototype.site = siteLocals;

return generator.call(self, siteLocals).then(function(data){
var interval = prettyHrtime(process.hrtime(start));
// Run generators
return Promise.reduce(keys, function(result, key){
var generator = generators[key];
var start = process.hrtime();

log.debug('Generator in %s: %s', chalk.cyan(interval), chalk.magenta(key));
return generator.call(self, siteLocals).then(function(data){
var interval = prettyHrtime(process.hrtime(start));

return data ? result.concat(data) : data;
});
}, []).each(function(item){
log.debug('Generator in %s: %s', chalk.cyan(interval), chalk.magenta(key));

return data ? result.concat(data) : data;
});
}, []);
})
.each(function(item){
// Add routes
if (item.path == null) return;

var path = route.format(item.path);
Expand All @@ -326,7 +335,7 @@ Hexo.prototype._generate = function(options){
var locals = new Locals(path, data);
var layoutLength = layout.length;

return self.extend.filter.exec('template_locals', locals, {context: self})
return self.execFilter('template_locals', locals, {context: self})
.then(function(locals){
route.set(path, function(){
var view, name;
Expand All @@ -345,13 +354,17 @@ Hexo.prototype._generate = function(options){
});
});
}).then(function(){
// Remove old routes
var removed = _.difference(routeList, newRouteList);

for (var i = 0, len = removed.length; i < len; i++){
route.remove(removed[i]);
}

self.emit('generateAfter');

// Run after_generate filters
return self.execFilter('after_generate', null, {context: self});
}).finally(function(){
self._isGenerating = false;
});
Expand All @@ -370,11 +383,19 @@ Hexo.prototype.exit = function(err){
);
}

return this.extend.filter.exec('before_exit', null, {context: this}).then(function(){
return this.execFilter('before_exit', null, {context: this}).then(function(){
self.emit('exit', err);
});
};

Hexo.prototype.execFilter = function(type, data, options){
return this.extend.filter.exec(type, data, options);
};

Hexo.prototype.execFilterSync = function(type, data, options){
return this.extend.filter.execSync(type, data, options);
};

Hexo.lib_dir = Hexo.prototype.lib_dir = libDir + sep;

Hexo.core_dir = Hexo.prototype.core_dir = pathFn.dirname(libDir) + sep;
Expand Down
56 changes: 51 additions & 5 deletions lib/hexo/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ var yaml = require('js-yaml');
var util = require('hexo-util');
var fs = require('hexo-fs');
var yfm = require('hexo-front-matter');
var vm = require('vm');
var swigFilters = require('swig/lib/filters');
var swigUtils = require('swig/lib/utils');
var swigParser = require('swig/lib/parser');

var slugize = util.slugize;
var escapeRegExp = util.escapeRegExp;
Expand Down Expand Up @@ -51,7 +55,7 @@ Post.prototype.create = function(data, replace, callback){

return Promise.all([
// Get the post path
ctx.extend.filter.exec('new_post_path', data, {
ctx.execFilter('new_post_path', data, {
args: [replace],
context: ctx
}),
Expand Down Expand Up @@ -199,11 +203,45 @@ Post.prototype.publish = function(data, replace, callback){
}).thenReturn(result).nodeify(callback);
};

function efn(){
return '';
}

function swigRender(swig, data){
// Swig.render extends the options which will cause "Maximum call stack size
// exceeded" error. I try to build a own compiler instead.
// Based on: https://github.com/paularmstrong/swig/blob/v1.4.2/lib/swig.js#L485
var src = data.content;
var tokens = swig.parse(src);

var options = {
filename: data.source,
locals: data
};

var sandbox = {
_swig: swig,
_ctx: {},
_filters: swigFilters,
_utils: swigUtils,
_fn: efn,
_output: '',
_ext: swig.extensions
};

// EXPERIMENTAL: run swig in a new context
// I don't use `new Function()` here because it's a form of eval and will cause
// lint error. But I don't know whether vm is slower or not.
vm.runInNewContext(swigParser.compile(tokens, [], options), sandbox);

return sandbox._output.trim();
}

Post.prototype.render = function(source, data, callback){
var ctx = this.context;
var filter = ctx.extend.filter;
var config = ctx.config;
var cache = [];
var swig = ctx.extend.tag.swig;

data = data || {};

Expand All @@ -215,7 +253,7 @@ Post.prototype.render = function(source, data, callback){
if (data.content != null) return resolve(data.content);
if (!source) return reject(new Error('No input file or string!'));

// Read content from files
// Read content from files
fs.readFile(source).then(resolve, reject);
}).then(function(content){
// Escape all swig tags
Expand All @@ -226,12 +264,17 @@ Post.prototype.render = function(source, data, callback){
.replace(rSwigBlock, escapeContent);

// Run "before_post_render" filters
return filter.exec('before_post_render', data, {context: ctx}).then(function(){
return ctx.execFilter('before_post_render', data, {context: ctx}).then(function(){
data.content = data.content.replace(rEscapeContent, function(match, content){
return placeholder + (cache.push(content) - 1);
});
});
}).then(function(){
// Skip render phase if this is a swig file
if ((source && pathFn.extname(source) === '.swig') || data.engine === 'swig'){
return data.content;
}

var options = data.markdown || {};
if (!config.highlight.enable) options.highlight = null;

Expand All @@ -251,8 +294,11 @@ Post.prototype.render = function(source, data, callback){
// Clean cache
cache.length = 0;

// Render with Swig
data.content = swigRender(swig, data);

// Run "after_post_render" filters
return filter.exec('after_post_render', data, {context: ctx});
return ctx.execFilter('after_post_render', data, {context: ctx});
});
};

Expand Down
61 changes: 0 additions & 61 deletions lib/models/common.js

This file was deleted.

21 changes: 5 additions & 16 deletions lib/models/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ var Schema = require('warehouse').Schema;
var pathFn = require('path');
var Moment = require('./types/moment');
var moment = require('moment');
var common = require('./common');
var CacheString = require('./types/cachestring');

module.exports = function(ctx){
var swig = ctx.extend.tag.swig;

var Page = new Schema({
title: {type: String, default: ''},
date: {
Expand All @@ -26,7 +24,10 @@ module.exports = function(ctx){
_content: {type: String, default: ''},
source: {type: String, required: true},
path: {type: String, required: true},
raw: {type: String, default: ''}
raw: {type: String, default: ''},
content: {type: CacheString, default: ''},
excerpt: {type: CacheString, default: ''},
more: {type: CacheString, default: ''}
});

Page.virtual('permalink').get(function(){
Expand All @@ -37,17 +38,5 @@ module.exports = function(ctx){
return pathFn.join(ctx.source_dir, this.source || '');
});

Page.virtual('content').get(function(){
return common.renderContent(swig, this);
});

Page.virtual('excerpt').get(function(){
return common.getExcerpt(this.content);
});

Page.virtual('more').get(function(){
return common.getMore(this.content);
});

return Page;
};
Loading

0 comments on commit 3ea11a7

Please sign in to comment.