-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ New fully-loaded & validated activeTheme concept (#8146)
📡 Add debug for the 3 theme activation methods There are 3 different ways that a theme can be activated in Ghost: A. On boot: we load the active theme from the file system, according to the `activeTheme` setting B. On API "activate": when an /activate/ request is triggered for a theme, we validate & change the `activeTheme` setting C. On API "override": if uploading a theme with the same name, we override. Using a dirty hack to make this work. A: setting is done, should load & validate + next request does mounting B: load is done, should validate & change setting + next request does mounting C: load, validate & setting are all done + a hack is needed to ensure the next request does mounting ✨ Validate w/ gscan when theme activating on boot - use the new gscan validation validate.check() method when activating on boot ✨ New concept of active theme - add ActiveTheme class - make it possible to set a theme to be active, and to get the active theme - call the new themes.activate() method in all 3 cases where we activate a theme 🎨 Use new activeTheme to simplify theme code - make use of the new concept where we can, to reduce & simplify code - use new hasPartials() method so we don't have to do file lookups - use path & name getters to reduce use of getContentPath etc - remove requirement on req.app.get('activeTheme') from static-theme middleware (more on this soon) 🚨 Improve theme unit tests (TODO: fix inter-dep) - The theme unit tests are borked! They all pass because they don't test the right things. - This improves them, but they are still dependent on each-other - configHbsForContext tests don't pass if the activateTheme tests aren't run first - I will fix this in a later PR
- Loading branch information
Showing
7 changed files
with
338 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
'use strict'; | ||
|
||
/** | ||
* # Active Theme | ||
* | ||
* This file defines a class of active theme, and also controls the getting and setting a single instance, as there | ||
* can only ever be one active theme. Unlike a singleton, the active theme can change, however only in a controlled way. | ||
* | ||
* I've made use of the new class & constructor syntax here, as we are now only supporting Node v4 and above, which has | ||
* full support for these features. | ||
* | ||
* There are several different patterns available for keeping data private. Elsewhere in Ghost we use the | ||
* naming convention of the _ prefix. Even though this has the downside of not being truly private, it is still one | ||
* of the preferred options for keeping data private with the new class syntax, therefore I have kept it. | ||
* | ||
* No properties marked with an _ should be used directly. | ||
* | ||
*/ | ||
var _ = require('lodash'), | ||
join = require('path').join, | ||
// Current instance of ActiveTheme | ||
currentActiveTheme; | ||
|
||
class ActiveTheme { | ||
/** | ||
* @TODO this API needs to be simpler, but for now should work! | ||
* @param {object} loadedTheme - the loaded theme object from the theme list | ||
* @param {object} checkedTheme - the result of gscan.format for the theme we're activating | ||
*/ | ||
constructor(loadedTheme, checkedTheme) { | ||
// Assign some data, mark it all as pseudo-private | ||
this._name = loadedTheme.name; | ||
this._path = loadedTheme.path; | ||
|
||
// @TODO: get gscan to return validated, useful package.json fields for us! | ||
this._packageInfo = loadedTheme['package.json']; | ||
this._partials = checkedTheme.partials; | ||
// @TODO: get gscan to return a template collection for us | ||
this._templates = _.reduce(checkedTheme.files, function (templates, entry) { | ||
var tplMatch = entry.file.match(/(^[^\/]+).hbs$/); | ||
if (tplMatch) { | ||
templates.push(tplMatch[1]); | ||
} | ||
return templates; | ||
}, []); | ||
} | ||
|
||
get name() { | ||
return this._name; | ||
} | ||
|
||
get path() { | ||
return this._path; | ||
} | ||
|
||
get partialsPath() { | ||
return join(this.path, 'partials'); | ||
} | ||
|
||
hasPartials() { | ||
return this._partials.length > 0; | ||
} | ||
|
||
hasTemplate(templateName) { | ||
return this._templates.indexOf(templateName) > -1; | ||
} | ||
} | ||
|
||
module.exports = { | ||
get() { | ||
return currentActiveTheme; | ||
}, | ||
/** | ||
* Set theme | ||
* | ||
* At this point we trust that the theme has been validated. | ||
* Any handling for invalid themes should happen before we get here | ||
* | ||
* @TODO this API needs to be simpler, but for now should work! | ||
* @param {object} loadedTheme - the loaded theme object from the theme list | ||
* @param {object} checkedTheme - the result of gscan.format for the theme we're activating | ||
* @return {ActiveTheme} | ||
*/ | ||
set(loadedTheme, checkedTheme) { | ||
currentActiveTheme = new ActiveTheme(loadedTheme, checkedTheme); | ||
return currentActiveTheme; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.