Ghost/core/frontend/services/theme-engine/active.js
Hannah Wolfe 9614d71e1f Moved theme i18n to new theme engine service
refs: bf0823c9a2

- continuing the work of splitting up the theme service into logical components

- This one is a little more involved, as the i18n initialisation was unnecessarily spread over several locations.
- I moved it into being part of the ActiveTheme class and called in the constructor, meaning we don't need the services.theme.activated event anymore as the constructor is called in the same cases.
- Also moved the event listener for locales into the bridge, as I don't want that inside of theme-engine, and we don't want circular dependencies. We'll figure out a wayto refactor this soon too.
2021-04-26 12:29:55 +01:00

137 lines
4.1 KiB
JavaScript

/**
* # 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.
*
* 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.
*
*/
const join = require('path').join;
const _ = require('lodash');
const themeConfig = require('./config');
const themeEngines = require('./engines');
const config = require('../../../shared/config');
const engine = require('./engine');
const themeI18n = require('./i18n');
// Current instance of ActiveTheme
let 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
* @param {object} error - bootstrap validates the active theme, we would like to remember this error
*/
constructor(loadedTheme, checkedTheme, error) {
// Assign some data, mark it all as pseudo-private
this._name = loadedTheme.name;
this._path = loadedTheme.path;
this._mounted = false;
this._error = error;
// @TODO: get gscan to return validated, useful package.json fields for us!
this._packageInfo = loadedTheme['package.json'];
this._partials = checkedTheme.partials;
// all custom .hbs templates (e.g. custom-about)
this._customTemplates = checkedTheme.templates.custom;
// all .hbs templates
this._templates = checkedTheme.templates.all;
// Create a theme config object
this._config = themeConfig.create(this._packageInfo);
// Create a theme engines object
this._engines = themeEngines.create(this._packageInfo);
this.initI18n();
}
get name() {
return this._name;
}
get customTemplates() {
return this._customTemplates;
}
get path() {
return this._path;
}
get partialsPath() {
return this._partials.length > 0 ? join(this.path, 'partials') : null;
}
get mounted() {
return this._mounted;
}
get error() {
return this._error;
}
hasTemplate(templateName) {
return this._templates.indexOf(templateName) > -1;
}
updateTemplateOptions(options) {
engine.updateTemplateOptions(_.merge({}, engine.getTemplateOptions(), options));
}
config(key) {
return this._config[key];
}
engine(key) {
return this._engines[key];
}
initI18n() {
themeI18n.init(this._name);
}
mount(siteApp) {
// reset the asset hash
// @TODO: set this on the theme instead of globally, or use proper file-based hash
config.set('assetHash', null);
// clear the view cache
siteApp.cache = {};
// Set the views and engine
siteApp.set('views', this.path);
siteApp.engine('hbs', engine.configure(this.partialsPath));
this._mounted = true;
}
}
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, error) {
currentActiveTheme = new ActiveTheme(loadedTheme, checkedTheme, error);
return currentActiveTheme;
}
};