diff --git a/lib/box/index.js b/lib/box/index.js index 9cd9cac238..8e4d6eacec 100644 --- a/lib/box/index.js +++ b/lib/box/index.js @@ -49,11 +49,21 @@ function Box(ctx, base, options){ options = {}; } - return ctx.render.render({path: this.source}, options).nodeify(callback); + var self = this; + + return this.read().then(function(content){ + return ctx.render.render({ + text: content, + path: self.source + }, options) + }).nodeify(callback); }; _File.prototype.renderSync = function(options){ - return ctx.render.renderSync({path: this.source}, options); + return ctx.render.renderSync({ + text: this.readSync(), + path: this.source + }, options); }; } diff --git a/lib/theme/index.js b/lib/theme/index.js index aeb45305a8..abf0efc7db 100644 --- a/lib/theme/index.js +++ b/lib/theme/index.js @@ -5,8 +5,6 @@ var util = require('../util'); var Box = require('../box'); var View = require('./view'); -var i18n = util.i18n; - require('colors'); function Theme(ctx){ @@ -14,27 +12,23 @@ function Theme(ctx){ this.config = {}; - this.i18n = new i18n({ - code: ctx.config.language - }); - this.views = {}; this.processors = [ require('./processors/config'), - require('./processors/i18n'), require('./processors/view'), require('./processors/source') ]; - var _View = this.View = function(path){ - View.call(this, path); + var _View = this.View = function(path, data){ + View.call(this, path, data); }; util.inherits(_View, View); - _View.prototype.theme = this; - _View.prototype.context = ctx; + _View.prototype._theme = this; + _View.prototype._render = ctx.render; + _View.prototype._helper = ctx.extend.helper; } util.inherits(Theme, Box); @@ -47,7 +41,6 @@ Theme.prototype._generate = function(options){ var ctx = this.context; var config = ctx.config; var siteLocals = ctx.locals; - var i18n = this.i18n; var generators = ctx.extend.generator.list(); var generatorKeys = Object.keys(generators); @@ -55,8 +48,7 @@ Theme.prototype._generate = function(options){ function Locals(path, locals){ this.page = _.extend({ - path: path, - lang: ensureLanguage(this) // every page should have a 'lang' value + path: path }, locals); this.path = path; @@ -67,8 +59,6 @@ Theme.prototype._generate = function(options){ Locals.prototype.config = config; Locals.prototype.theme = _.extend({}, config, this.config, config.theme_config); Locals.prototype._ = _; - Locals.prototype.__ = i18n.__(); - Locals.prototype._p = i18n._p(); Locals.prototype.layout = 'layout'; Locals.prototype.cache = !options.watch; Locals.prototype.env = ctx.env; @@ -91,21 +81,6 @@ Theme.prototype._generate = function(options){ }); }; -function ensureLanguage(locals){ - var page = locals.page; - var lang = page.lang; - var config = locals.config; - - if (lang) return lang; - if (!config.language) return 'default'; - if (!Array.isArray(config.language)) return config.language; - - var path = locals.path; - if (path[0] !== '/') path = '/' + path; - - // TODO: Optimize language query -} - Theme.prototype.generate = function(options, callback){ if (!callback && typeof options === 'function'){ callback = options; @@ -137,4 +112,22 @@ Theme.prototype.getView = function(path){ } }; +Theme.prototype.setView = function(path, data){ + var extname = pathFn.extname(path); + var name = path.substring(0, path.length - extname.length); + var views = this.views[name] = this.views[name] || {}; + + views[extname] = new this.View(path, data); +}; + +Theme.prototype.removeView = function(path){ + var extname = pathFn.extname(path); + var name = path.substring(0, path.length - extname.length); + var views = this.views[name]; + + if (!views) return; + + delete views[extname]; +}; + module.exports = Theme; \ No newline at end of file diff --git a/lib/theme/processors/config.js b/lib/theme/processors/config.js index 17f348e798..32db410652 100644 --- a/lib/theme/processors/config.js +++ b/lib/theme/processors/config.js @@ -1,18 +1,18 @@ var Pattern = require('../../box/pattern'); -exports.process = function(data){ - if (data.type === 'delete'){ - this.config = {}; +exports.process = function(file){ + if (file.type === 'delete'){ + file.box.config = {}; return; } - var ctx = this.context; + var self = this; - return data.render().then(function(result){ - data.box.config = result; - ctx.log.debug('Theme config loaded.'); + return file.render().then(function(result){ + file.box.config = result; + self.log.debug('Theme config loaded.'); }, function(err){ - ctx.log.error('Theme config load failed.'); + self.log.error('Theme config load failed.'); throw err; }); }; diff --git a/lib/theme/processors/i18n.js b/lib/theme/processors/i18n.js deleted file mode 100644 index 5c8be782f4..0000000000 --- a/lib/theme/processors/i18n.js +++ /dev/null @@ -1,20 +0,0 @@ -var pathFn = require('path'); -var Pattern = require('../../box/pattern'); - -exports.process = function(data){ - var path = data.params.path; - var extname = pathFn.extname(path); - var name = pathFn.substring(0, path.length - extname.length); - var i18n = this.i18n; - - if (data.type === 'delete'){ - i18n.remove(name); - return; - } - - return data.render().then(function(result){ - i18n.set(name, result); - }); -}; - -exports.pattern = new Pattern('languages/*path'); \ No newline at end of file diff --git a/lib/theme/processors/source.js b/lib/theme/processors/source.js index 8d0a0323e0..6258872536 100644 --- a/lib/theme/processors/source.js +++ b/lib/theme/processors/source.js @@ -1,16 +1,38 @@ var Pattern = require('../../box/pattern'); +var common = require('../../plugins/processor/common'); -var rHiddenFile = /^_|\/_/; +exports.process = function(file){ + var Asset = this.model('Asset'); + var id = file.source.substring(this.base_dir.length); + var path = file.params.path; + var doc = Asset.findById(id); -exports.process = function(data){ - // + if (file.type === 'delete'){ + if (doc){ + return doc.remove(); + } else { + return; + } + } + + if (doc){ + doc.path = path; + doc.modified = file.type === 'update'; + + return doc.save(); + } else { + return Asset.insert({ + _id: id, + path: path + }); + } }; exports.pattern = new Pattern(function(path){ - if (path.substring(0, 6) !== 'source') return; + if (path.substring(0, 7) !== 'source/') return false; path = path.substring(7); - if (rHiddenFile.test(path)) return; + if (common.isHiddenFile(path) || common.isTmpFile(path)) return false; return {path: path}; }); \ No newline at end of file diff --git a/lib/theme/processors/view.js b/lib/theme/processors/view.js index 1b607b97c5..3b70c72a9c 100644 --- a/lib/theme/processors/view.js +++ b/lib/theme/processors/view.js @@ -1,7 +1,17 @@ var Pattern = require('../../box/pattern'); +var pathFn = require('path'); -exports.process = function(data){ - // +exports.process = function(file){ + var path = file.params.path; + + if (file.type === 'delete'){ + file.box.removeView(path); + return; + } + + return file.read().then(function(result){ + file.box.setView(path, result); + }); }; exports.pattern = new Pattern('layout/*path'); \ No newline at end of file diff --git a/lib/theme/view.js b/lib/theme/view.js index 86500a3e4d..e99fc986b6 100644 --- a/lib/theme/view.js +++ b/lib/theme/view.js @@ -3,13 +3,8 @@ var _ = require('lodash'); var yfm = require('hexo-front-matter'); function View(path, data){ - var ctx = this.context; - this.path = path; - this.source = pathFn.join(this.theme.base, path); - this.extname = pathFn.extname(path); - this.render = ctx.render; - this.helper = ctx.extend.helper; + this.source = pathFn.join(this._theme.base, 'layout', path); this.data = typeof data === 'string' ? yfm(data) : data; } @@ -26,7 +21,7 @@ View.prototype.render = function(options, callback){ var locals = this._buildLocals(options); var self = this; - return this.render.render({ + return this._render.render({ path: this.source, text: data._content }, this._bindHelpers(locals)).then(function(result){ @@ -50,7 +45,7 @@ View.prototype.renderSync = function(options){ var layout = data.hasOwnProperty('layout') ? data.layout : options.layout; var locals = this._buildLocals(options); - var result = this.render.renderSync({ + var result = this._render.renderSync({ path: this.source, text: data._content }, this._bindHelpers(locals)); @@ -97,7 +92,7 @@ View.prototype._buildLocals = function(locals){ }; View.prototype._bindHelpers = function(locals){ - var helpers = this.helper.list(); + var helpers = this._helper.list(); var keys = Object.keys(helpers); var result = {}; var key = ''; @@ -115,12 +110,12 @@ View.prototype._bindHelpers = function(locals){ View.prototype._resolveLayout = function(name){ // Relative path var layoutPath = pathFn.join(pathFn.dirname(this.path), name); - var layoutView = this.theme.getView(layoutPath); + var layoutView = this._theme.getView(layoutPath); if (layoutView && layoutView.source !== this.source) return layoutView; // Absolute path - layoutView = this.theme.getView(name); + layoutView = this._theme.getView(name); if (layoutView && layoutView.source !== this.source) return layoutView; }; diff --git a/lib/util/i18n.js b/lib/util/i18n.js index c213fc190c..20d758c83f 100644 --- a/lib/util/i18n.js +++ b/lib/util/i18n.js @@ -1,5 +1,5 @@ -var _ = require('lodash'), - vsprintf = require('sprintf-js').vsprintf; +var _ = require('lodash'); +var vsprintf = require('sprintf-js').vsprintf; /** * i18n module. @@ -10,7 +10,7 @@ var _ = require('lodash'), * @constructor * @module hexo */ -var i18n = module.exports = function i18n(options){ +function i18n(options){ /** * Language data. * @@ -29,7 +29,7 @@ var i18n = module.exports = function i18n(options){ code: 'default' }, options); - this.options.code = _getCodeToken(this.options.code); + this.options.code = getCodeToken(this.options.code); }; /** @@ -84,12 +84,12 @@ var _getProperty = function(obj, key){ return cursor; }; -var _getCodeToken = function(code){ +function getCodeToken(code){ var arr = []; if (Array.isArray(code)){ code.forEach(function(item){ - arr = arr.concat(_getCodeToken(item)); + arr = arr.concat(getCodeToken(item)); }); } else if (code){ var split = code.split('-'); @@ -102,7 +102,7 @@ var _getCodeToken = function(code){ } return arr; -}; +} /** * Parses the language code. @@ -112,7 +112,7 @@ var _getCodeToken = function(code){ * @return {Array} */ i18n.prototype._parseCode = function(code){ - var arr = [].concat(_getCodeToken(code), this.options.code); + var arr = [].concat(getCodeToken(code), this.options.code); if (arr.indexOf('default') === -1){ arr.push('default'); @@ -206,3 +206,5 @@ i18n.prototype._p = function(code){ return _p; }; + +module.exports = i18n; \ No newline at end of file diff --git a/test/index.js b/test/index.js index c0276f16e1..2f566964e1 100644 --- a/test/index.js +++ b/test/index.js @@ -9,5 +9,7 @@ describe('Hexo', function(){ require('./scripts/processors'); require('./scripts/renderers'); require('./scripts/tags'); + require('./scripts/theme'); + require('./scripts/theme_processors') require('./scripts/util'); }); \ No newline at end of file diff --git a/test/scripts/box/file.js b/test/scripts/box/file.js index 187b3a3a99..f8ba405aa5 100644 --- a/test/scripts/box/file.js +++ b/test/scripts/box/file.js @@ -187,7 +187,11 @@ describe('File', function(){ }); }); + it('render() - use cache'); + it('renderSync()', function(){ file.renderSync().should.eql(obj); }); + + it('renderSync() - use cache'); }); \ No newline at end of file diff --git a/test/scripts/theme/index.js b/test/scripts/theme/index.js new file mode 100644 index 0000000000..287bcbc966 --- /dev/null +++ b/test/scripts/theme/index.js @@ -0,0 +1,4 @@ +describe('Theme', function(){ + require('./theme'); + require('./view'); +}); \ No newline at end of file diff --git a/test/scripts/theme/theme.js b/test/scripts/theme/theme.js new file mode 100644 index 0000000000..39424ea694 --- /dev/null +++ b/test/scripts/theme/theme.js @@ -0,0 +1,64 @@ +var should = require('chai').should(); +var pathFn = require('path'); +var fs = require('hexo-fs'); +var Promise = require('bluebird'); + +describe('Theme', function(){ + var Hexo = require('../../../lib/hexo'); + var hexo = new Hexo(pathFn.join(__dirname, 'theme_test')); + var themeDir = pathFn.join(hexo.base_dir, 'themes', 'test'); + + before(function(){ + return Promise.all([ + fs.mkdirs(themeDir), + fs.writeFile(hexo.config_path, 'theme: test') + ]).then(function(){ + return hexo.init(); + }); + }); + + after(function(){ + return fs.rmdir(hexo.base_dir); + }); + + it('generate()'); + + it('getView()', function(){ + hexo.theme.setView('test.swig', ''); + + // With extension name + hexo.theme.getView('test.swig').should.have.property('path', 'test.swig'); + + // Without extension name + hexo.theme.getView('test').should.have.property('path', 'test.swig'); + + // not exist + should.not.exist(hexo.theme.getView('abc.swig')); + + hexo.theme.removeView('test.swig'); + }); + + it('getView() - escape backslashes', function(){ + hexo.theme.setView('foo/bar.swig', ''); + + hexo.theme.getView('foo\\bar.swig').should.have.property('path', 'foo/bar.swig'); + + hexo.theme.removeView('foo/bar.swig'); + }); + + it('setView()', function(){ + hexo.theme.setView('test.swig', ''); + + var view = hexo.theme.getView('test.swig'); + view.path.should.eql('test.swig'); + + hexo.theme.removeView('test.swig'); + }); + + it('removeView()', function(){ + hexo.theme.setView('test.swig', ''); + hexo.theme.removeView('test.swig'); + + should.not.exist(hexo.theme.getView('test.swig')); + }); +}); \ No newline at end of file diff --git a/test/scripts/theme/view.js b/test/scripts/theme/view.js new file mode 100644 index 0000000000..514b59070a --- /dev/null +++ b/test/scripts/theme/view.js @@ -0,0 +1,228 @@ +var should = require('chai').should(); +var pathFn = require('path'); +var fs = require('hexo-fs'); +var Promise = require('bluebird'); +var moment = require('moment'); + +describe('View', function(){ + var Hexo = require('../../../lib/hexo'); + var hexo = new Hexo(pathFn.join(__dirname, 'theme_test')); + var themeDir = pathFn.join(hexo.base_dir, 'themes', 'test'); + + function newView(path, data){ + return new hexo.theme.View(path, data); + } + + before(function(){ + return Promise.all([ + fs.mkdirs(themeDir), + fs.writeFile(hexo.config_path, 'theme: test') + ]).then(function(){ + return hexo.init(); + }).then(function(){ + // Setup layout + hexo.theme.setView('layout.swig', [ + 'pre', + '{{ body }}', + 'post' + ].join('\n')); + }); + }); + + after(function(){ + return fs.rmdir(hexo.base_dir); + }); + + it('constructor', function(){ + var view = newView('index.swig', {}); + + view.path.should.eql('index.swig'); + view.source.should.eql(pathFn.join(themeDir, 'layout', 'index.swig')); + view.data.should.eql({}); + }); + + it('parse front-matter', function(){ + var body = [ + 'layout: false', + '---', + 'content' + ].join('\n'); + + var view = newView('index.swig', body); + + view.data.should.eql({ + layout: false, + _content: 'content' + }); + }); + + it('render()', function(){ + var body = [ + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + + return view.render({ + test: 'foo' + }).then(function(content){ + content.should.eql('foo'); + }); + }); + + it('render() - front-matter', function(){ + // The priority of front-matter is higher + var body = [ + 'foo: bar', + '---', + '{{ foo }}', + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + + return view.render({ + foo: 'foo', + test: 'test' + }).then(function(content){ + content.should.eql('bar\ntest'); + }); + }); + + it('render() - helper', function(){ + var body = [ + '{{ date() }}' + ].join('\n'); + + var view = newView('index.swig', body); + + return view.render({ + config: hexo.config + }).then(function(content){ + content.should.eql(moment().format(hexo.config.date_format)); + }); + }); + + it('render() - layout', function(){ + var body = 'content'; + var view = newView('index.swig', body); + + return view.render({ + layout: 'layout' + }).then(function(content){ + content.should.eql('pre\n' + body + '\npost'); + }); + }); + + it('render() - layout not found', function(){ + var body = 'content'; + var view = newView('index.swig', body); + + return view.render({ + layout: 'wtf' + }).then(function(content){ + content.should.eql(body); + }); + }); + + it('render() - callback', function(callback){ + var body = [ + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + + view.render({ + test: 'foo' + }, function(err, content){ + should.not.exist(err); + content.should.eql('foo'); + callback(); + }); + }); + + it('render() - callback (without options)', function(callback){ + var body = [ + 'test: foo', + '---', + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + + view.render(function(err, content){ + should.not.exist(err); + content.should.eql('foo'); + callback(); + }); + }); + + it('renderSync()', function(){ + var body = [ + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + view.renderSync({test: 'foo'}).should.eql('foo'); + }); + + it('renderSync() - front-matter', function(){ + // The priority of front-matter is higher + var body = [ + 'foo: bar', + '---', + '{{ foo }}', + '{{ test }}' + ].join('\n'); + + var view = newView('index.swig', body); + + view.renderSync({ + foo: 'foo', + test: 'test' + }).should.eql('bar\ntest'); + }); + + it('renderSync() - helper', function(){ + var body = [ + '{{ date() }}' + ].join('\n'); + + var view = newView('index.swig', body); + + view.renderSync({ + config: hexo.config + }).should.eql(moment().format(hexo.config.date_format)); + }); + + it('renderSync() - layout', function(){ + var body = 'content'; + var view = newView('index.swig', body); + + view.renderSync({ + layout: 'layout' + }).should.eql('pre\n' + body + '\npost'); + }); + + it('renderSync() - layout not found', function(){ + var body = 'content'; + var view = newView('index.swig', body); + + view.renderSync({ + layout: 'wtf' + }).should.eql(body); + }); + + it('_resolveLayout()', function(){ + var view = newView('partials/header.swig', 'header'); + + // Relative path + view._resolveLayout('../layout').should.have.property('path', 'layout.swig'); + + // Absolute path + view._resolveLayout('layout').should.have.property('path', 'layout.swig'); + + // Can't be itself + should.not.exist(view._resolveLayout('header')); + }); +}); \ No newline at end of file diff --git a/test/scripts/theme_processors/config.js b/test/scripts/theme_processors/config.js new file mode 100644 index 0000000000..cc5937f4bd --- /dev/null +++ b/test/scripts/theme_processors/config.js @@ -0,0 +1,87 @@ +var should = require('chai').should(); +var pathFn = require('path'); +var fs = require('hexo-fs'); +var Promise = require('bluebird'); + +describe('config', function(){ + var Hexo = require('../../../lib/hexo'); + var hexo = new Hexo(pathFn.join(__dirname, 'config_test'), {silent: true}); + var processor = require('../../../lib/theme/processors/config'); + var process = Promise.method(processor.process.bind(hexo)); + var themeDir = pathFn.join(hexo.base_dir, 'themes', 'test'); + + function newFile(options){ + options.source = pathFn.join(themeDir, options.path); + return new hexo.theme.File(options); + } + + before(function(){ + return Promise.all([ + fs.mkdirs(themeDir), + fs.writeFile(hexo.config_path, 'theme: test') + ]).then(function(){ + return hexo.init(); + }); + }); + + after(function(){ + return fs.rmdir(hexo.base_dir); + }); + + it('pattern', function(){ + var pattern = processor.pattern; + + pattern.match('_config.yml').should.be.ok; + pattern.match('_config.json').should.be.ok; + should.not.exist(pattern.match('_config/foo.yml')); + should.not.exist(pattern.match('foo.yml')); + }); + + it('type: create', function(){ + var body = [ + 'name:', + ' first: John', + ' last: Doe' + ].join('\n'); + + var file = newFile({ + path: '_config.yml', + type: 'create', + content: body + }); + + return process(file).then(function(){ + hexo.theme.config.should.eql({ + name: {first: 'John', last: 'Doe'} + }); + + hexo.theme.config = {}; + }); + }); + + it('type: delete', function(){ + var file = newFile({ + path: '_config.yml', + type: 'delete' + }); + + hexo.theme.config = {foo: 'bar'}; + + return process(file).then(function(){ + hexo.theme.config.should.eql({}); + }); + }); + + it('load failed', function(){ + var body = 'foo:bar'; + + var file = newFile({ + path: '_config.yml', + type: 'create' + }); + + return process(file).catch(function(err){ + err.should.have.property('message', 'Theme config load failed.'); + }).catch(function(){}); // Catch again because it throws error + }); +}); \ No newline at end of file diff --git a/test/scripts/theme_processors/index.js b/test/scripts/theme_processors/index.js new file mode 100644 index 0000000000..7e380ade5a --- /dev/null +++ b/test/scripts/theme_processors/index.js @@ -0,0 +1,5 @@ +describe('Theme processors', function(){ + require('./config'); + require('./source'); + require('./view'); +}); \ No newline at end of file diff --git a/test/scripts/theme_processors/source.js b/test/scripts/theme_processors/source.js new file mode 100644 index 0000000000..74af76da54 --- /dev/null +++ b/test/scripts/theme_processors/source.js @@ -0,0 +1,130 @@ +var should = require('chai').should(); +var pathFn = require('path'); +var fs = require('hexo-fs'); +var Promise = require('bluebird'); + +describe('source', function(){ + var Hexo = require('../../../lib/hexo'); + var hexo = new Hexo(pathFn.join(__dirname, 'source_test'), {silent: true}); + var processor = require('../../../lib/theme/processors/source'); + var process = Promise.method(processor.process.bind(hexo)); + var themeDir = pathFn.join(hexo.base_dir, 'themes', 'test'); + var Asset = hexo.model('Asset'); + + function newFile(options){ + var path = options.path; + + options.params = {path: path}; + options.path = 'source/' + path; + options.source = pathFn.join(themeDir, options.path); + + return new hexo.theme.File(options); + } + + before(function(){ + return Promise.all([ + fs.mkdirs(themeDir), + fs.writeFile(hexo.config_path, 'theme: test') + ]).then(function(){ + return hexo.init(); + }); + }); + + after(function(){ + return fs.rmdir(hexo.base_dir); + }); + + it('pattern', function(){ + var pattern = processor.pattern; + + pattern.match('source/foo.jpg').should.eql({path: 'foo.jpg'}); + pattern.match('source/_foo.jpg').should.be.false; + pattern.match('source/foo/_bar.jpg').should.be.false; + pattern.match('source/foo.jpg~').should.be.false; + pattern.match('source/foo.jpg%').should.be.false; + pattern.match('layout/foo.swig').should.be.false; + pattern.match('package.json').should.be.false; + }); + + it('type: create', function(){ + var file = newFile({ + path: 'style.css', + type: 'create' + }); + + return process(file).then(function(){ + var id = 'themes/test/' + file.path; + var asset = Asset.findById(id); + + asset._id.should.eql(id); + asset.path.should.eql(file.params.path); + asset.modified.should.be.true; + + return asset.remove(); + }); + }); + + it('type: update', function(){ + var file = newFile({ + path: 'style.css', + type: 'update' + }); + + var id = 'themes/test/' + file.path; + + return Asset.insert({ + _id: id, + path: file.params.path, + modified: false + }).then(function(){ + return process(file); + }).then(function(){ + var asset = Asset.findById(id); + + asset.modified.should.be.true; + + return asset.remove(); + }); + }); + + it('type: skip', function(){ + var file = newFile({ + path: 'style.css', + type: 'skip' + }); + + var id = 'themes/test/' + file.path; + + return Asset.insert({ + _id: id, + path: file.params.path, + modified: true + }).then(function(){ + return process(file); + }).then(function(){ + var asset = Asset.findById(id); + + asset.modified.should.be.false; + + return asset.remove(); + }); + }); + + it('type: delete', function(){ + var file = newFile({ + path: 'style.css', + type: 'delete' + }); + + var id = 'themes/test/' + file.path; + + return Asset.insert({ + _id: id, + path: file.params.path + }).then(function(){ + return process(file); + }).then(function(){ + should.not.exist(Asset.findById(id)); + }); + }); +}); \ No newline at end of file diff --git a/test/scripts/theme_processors/view.js b/test/scripts/theme_processors/view.js new file mode 100644 index 0000000000..c47f505fd5 --- /dev/null +++ b/test/scripts/theme_processors/view.js @@ -0,0 +1,81 @@ +var should = require('chai').should(); +var pathFn = require('path'); +var fs = require('hexo-fs'); +var Promise = require('bluebird'); + +describe('view', function(){ + var Hexo = require('../../../lib/hexo'); + var hexo = new Hexo(pathFn.join(__dirname, 'view_test'), {silent: true}); + var processor = require('../../../lib/theme/processors/view'); + var process = Promise.method(processor.process.bind(hexo)); + var themeDir = pathFn.join(hexo.base_dir, 'themes', 'test'); + + function newFile(options){ + var path = options.path; + + options.params = {path: path}; + options.path = 'layout/' + path; + options.source = pathFn.join(themeDir, options.path); + + return new hexo.theme.File(options); + } + + before(function(){ + return Promise.all([ + fs.mkdirs(themeDir), + fs.writeFile(hexo.config_path, 'theme: test') + ]).then(function(){ + return hexo.init(); + }); + }); + + after(function(){ + return fs.rmdir(hexo.base_dir); + }); + + it('pattern', function(){ + var pattern = processor.pattern; + + pattern.match('layout/index.swig').path.should.eql('index.swig'); + should.not.exist(pattern.match('index.swig')); + should.not.exist(pattern.match('view/index.swig')); + }); + + it('type: create', function(){ + var body = [ + 'foo: bar', + '---', + 'test' + ].join('\n'); + + var file = newFile({ + path: 'index.swig', + type: 'create', + content: new Buffer(body) + }); + + return process(file).then(function(){ + var view = hexo.theme.getView('index.swig'); + + view.path.should.eql('index.swig'); + view.source.should.eql(pathFn.join(themeDir, 'layout', 'index.swig')); + view.data.should.eql({ + foo: 'bar', + _content: 'test' + }); + + hexo.theme.removeView('index.swig'); + }); + }); + + it('type: delete', function(){ + var file = newFile({ + path: 'index.swig', + type: 'delete' + }); + + return process(file).then(function(){ + should.not.exist(hexo.theme.getView('index.swig')); + }); + }); +}); \ No newline at end of file