Directory scanning on contents/themes and plugins
This implements #106. * Added require-tree which is based off of @ricardobeat's module. Fully async. * I've moved active theme and active directory to settings from config as well. * Modified settings.hbs and settings.js to display the raw json under Settings/Appearance
This commit is contained in:
parent
1df9b6e90a
commit
e271c6402f
24
app.js
24
app.js
@ -45,13 +45,7 @@
|
||||
ghost.app().use(ghost.initTheme(ghost.app()));
|
||||
ghost.app().use(flash());
|
||||
// bind locals - options which appear in every view - perhaps this should be admin only
|
||||
ghost.app().use(function (req, res, next) {
|
||||
res.locals.messages = req.flash();
|
||||
res.locals.siteTitle = ghostGlobals.title;
|
||||
res.locals.siteDescription = ghostGlobals.description;
|
||||
res.locals.siteUrl = ghostGlobals.url;
|
||||
next();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
@ -88,6 +82,8 @@
|
||||
// Make sure we have a locals value.
|
||||
res.locals = res.locals || {};
|
||||
|
||||
|
||||
|
||||
// Extend it with nav data and ghostGlobals
|
||||
_.extend(res.locals, navData, {
|
||||
ghostGlobals: ghost.globals()
|
||||
@ -101,10 +97,22 @@
|
||||
ghost.loaded = loading.promise;
|
||||
|
||||
when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers(ghost)]).then(function () {
|
||||
|
||||
// Assign the globals we have loaded
|
||||
ghostGlobals = ghost.globals();
|
||||
|
||||
ghost.app().use(function (req, res, next) {
|
||||
res.locals.messages = req.flash();
|
||||
res.locals.siteTitle = ghostGlobals.title;
|
||||
res.locals.siteDescription = ghostGlobals.description;
|
||||
res.locals.siteUrl = ghostGlobals.url;
|
||||
res.locals.activeTheme = ghostGlobals.activeTheme;
|
||||
res.locals.activePlugin = ghostGlobals.activePlugin;
|
||||
res.locals.availableThemes = ghost.paths().availableThemes;
|
||||
res.locals.availablePlugins = ghost.paths().availablePlugins;
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* API routes..
|
||||
* @todo auth should be public auth not user auth
|
||||
|
@ -13,7 +13,7 @@
|
||||
<li class="general active"><a href="#general">General</a></li>
|
||||
<li class="publishing"><a href="#content">Content</a></li>
|
||||
<li class="users"><a href="#users">Users</a></li>
|
||||
<li class="appearance"><a href="#">Appearance</a></li>
|
||||
<li class="appearance"><a href="#appearance">Appearance</a></li>
|
||||
<li class="services"><a href="#">Connected Services</a></li>
|
||||
<li class="plugins"><a href="#">Plugins</a></li>
|
||||
</ul>
|
||||
@ -200,4 +200,17 @@
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="appearance" class="settings-content">
|
||||
<header>
|
||||
<h2 class="title">Appearance</h2>
|
||||
</header>
|
||||
<section class="content">
|
||||
<h6 class="sub">Raw json be here</h6>
|
||||
<p>Active theme: {{json settings.activeTheme}}</p>
|
||||
<p>Available themes: {{json availableThemes}}</p>
|
||||
<p>Available plugins: {{json availablePlugins}}</p>
|
||||
|
||||
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
@ -40,6 +40,10 @@
|
||||
return output;
|
||||
});
|
||||
|
||||
ghost.registerThemeHelper('json', function (object, options) {
|
||||
return JSON.stringify(object);
|
||||
});
|
||||
|
||||
return when.all([
|
||||
// Just one async helper for now, but could be more in the future
|
||||
navHelper.registerWithGhost(ghost)
|
||||
|
@ -16,6 +16,11 @@
|
||||
|
||||
models = require('./shared/models'),
|
||||
ExampleFilter = require('../content/plugins/exampleFilters'),
|
||||
|
||||
requireTree = require('./shared/require-tree'),
|
||||
themeDirectories = requireTree('content/themes'),
|
||||
pluginDirectories = requireTree('content/plugins'),
|
||||
|
||||
Ghost,
|
||||
instance,
|
||||
defaults,
|
||||
@ -59,10 +64,17 @@
|
||||
instance = this;
|
||||
|
||||
// Holds the filters
|
||||
this.filterCallbacks = [];
|
||||
instance.filterCallbacks = [];
|
||||
|
||||
// Holds the filter hooks (that are built in to Ghost Core)
|
||||
this.filters = [];
|
||||
instance.filters = [];
|
||||
|
||||
// Holds the theme directories temporarily
|
||||
instance.themeDirectories = {};
|
||||
|
||||
// Holds the plugin directories temporarily
|
||||
instance.pluginDirectories = {};
|
||||
|
||||
|
||||
plugin = new ExampleFilter(instance).init();
|
||||
|
||||
@ -74,32 +86,44 @@
|
||||
// load Plugins...
|
||||
// var f = new FancyFirstChar(ghost).init();
|
||||
|
||||
|
||||
|
||||
_.extend(instance, {
|
||||
app: function () { return app; },
|
||||
config: function () { return config; },
|
||||
globals: function () { return instance.globalConfig; }, // there's no management here to be sure this has loaded
|
||||
|
||||
// there's no management here to be sure this has loaded
|
||||
globals: function () { return instance.globalConfig; },
|
||||
dataProvider: models,
|
||||
statuses: function () { return statuses; },
|
||||
polyglot: function () { return polyglot; },
|
||||
plugin: function () { return plugin; },
|
||||
getPaths: function () {
|
||||
return when.all([themeDirectories, pluginDirectories]).then(function (paths) {
|
||||
instance.themeDirectories = paths[0];
|
||||
instance.pluginDirectories = paths[1];
|
||||
return;
|
||||
});
|
||||
},
|
||||
paths: function () {
|
||||
return {
|
||||
'activeTheme': __dirname + '/../content/' + config.themeDir + '/' + config.activeTheme + '/',
|
||||
'adminViews': __dirname + '/admin/views/',
|
||||
'frontendViews': __dirname + '/frontend/views/',
|
||||
'lang': __dirname + '/lang/'
|
||||
'lang': __dirname + '/lang/',
|
||||
'availableThemes': instance.themeDirectories,
|
||||
'availablePlugins': instance.pluginDirectories
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
Ghost.prototype.init = function () {
|
||||
this.globalConfig = config.blogData;
|
||||
return when.all([instance.dataProvider.init()]);
|
||||
|
||||
return when.all([instance.dataProvider.init(), instance.getPaths()]);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -186,7 +210,6 @@
|
||||
var self = this;
|
||||
return function initTheme(req, res, next) {
|
||||
app.set('view engine', 'hbs');
|
||||
|
||||
if (/(^\/ghost$|^\/ghost\/)/.test(req.url) === false) {
|
||||
app.engine('hbs', hbs.express3(
|
||||
{partialsDir: self.paths().activeTheme + 'partials'}
|
||||
@ -199,7 +222,6 @@
|
||||
}
|
||||
app.use(express['static'](self.paths().activeTheme));
|
||||
app.use('/content/images', express['static'](path.join(__dirname, '/../content/images')));
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
@ -60,6 +60,20 @@ module.exports = {
|
||||
"created_by": 1,
|
||||
"updated_by": 1,
|
||||
"type": "general"
|
||||
},
|
||||
{
|
||||
"key": "activePlugins",
|
||||
"value": "",
|
||||
"created_by": 1,
|
||||
"updated_by": 1,
|
||||
"type": "general"
|
||||
},
|
||||
{
|
||||
"key": "activeTheme",
|
||||
"value": "content/themes/casper",
|
||||
"created_by": 1,
|
||||
"updated_by": 1,
|
||||
"type": "general"
|
||||
}
|
||||
],
|
||||
|
||||
|
64
core/shared/require-tree.js
Normal file
64
core/shared/require-tree.js
Normal file
@ -0,0 +1,64 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
var when = require('when'),
|
||||
keys = require('when/keys'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
extend = function (obj, source) {
|
||||
var key;
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
obj[key] = source[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
readDir = function (dir, options, depth) {
|
||||
depth = depth || 0;
|
||||
|
||||
options = extend({
|
||||
index: true
|
||||
}, options);
|
||||
|
||||
if (depth > 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var subtree = {},
|
||||
treeDeferred = when.defer(),
|
||||
treePromise = treeDeferred.promise;
|
||||
|
||||
fs.readdir(dir, function (error, files) {
|
||||
files.forEach(function (file) {
|
||||
var fileDeferred = when.defer(),
|
||||
filePromise = fileDeferred.promise,
|
||||
ext = path.extname(file),
|
||||
name = path.basename(file, ext),
|
||||
fpath = path.join(dir, file);
|
||||
subtree[name] = filePromise;
|
||||
fs.lstat(fpath, function (error, result) {
|
||||
if (result.isDirectory()) {
|
||||
fileDeferred.resolve(readDir(fpath, options, depth + 1));
|
||||
} else {
|
||||
fileDeferred.resolve(fpath);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return keys.all(subtree).then(function(theFiles) {
|
||||
return treeDeferred.resolve(theFiles);
|
||||
});
|
||||
});
|
||||
|
||||
return when(treePromise).then(function (prom) {
|
||||
return prom;
|
||||
});
|
||||
},
|
||||
readAll = function (dir, options, depth) {
|
||||
return when(readDir(dir, options, depth)).then(function (paths) {
|
||||
return paths;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = readAll;
|
||||
}());
|
Loading…
Reference in New Issue
Block a user