From 3510094665c2b4b09729a21e018f371ec54e100c Mon Sep 17 00:00:00 2001 From: Al McKinlay Date: Fri, 5 Jan 2018 17:40:34 +0000 Subject: [PATCH] Allow custom css from plugins --- client/index.html | 3 ++ src/plugins/packages/index.js | 72 ++++++++++++++++++++++++++++ src/plugins/packages/themes.js | 66 ++++++++++++++++++++++++++ src/plugins/themes.js | 85 ---------------------------------- src/server.js | 28 ++++++++++- 5 files changed, 167 insertions(+), 87 deletions(-) create mode 100644 src/plugins/packages/index.js create mode 100644 src/plugins/packages/themes.js delete mode 100644 src/plugins/themes.js diff --git a/client/index.html b/client/index.html index 4c6a05b4..1560e0a8 100644 --- a/client/index.html +++ b/client/index.html @@ -11,6 +11,9 @@ + <% _.forEach(stylesheets, function(css) { %> + + <% }); %> The Lounge diff --git a/src/plugins/packages/index.js b/src/plugins/packages/index.js new file mode 100644 index 00000000..080e1094 --- /dev/null +++ b/src/plugins/packages/index.js @@ -0,0 +1,72 @@ +"use strict"; + +const fs = require("fs"); +const colors = require("colors/safe"); +const Helper = require("../../helper"); +const themes = require("./themes"); +const packageMap = new Map(); + +const stylesheets = []; + +module.exports = { + getStylesheets, + getPackage, + loadPackages, +}; + +const packageApis = function(packageName) { + return { + Stylesheets: { + addFile: addStylesheet.bind(this, packageName), + }, + }; +}; + +function addStylesheet(packageName, filename) { + stylesheets.push(packageName + "/" + filename); +} + +function getStylesheets() { + return stylesheets; +} + +function getPackage(name) { + return packageMap.get(name); +} + +function loadPackages() { + fs.readdir(Helper.getPackagesPath(), (err, packages) => { + if (err) { + return; + } + packages.forEach((packageName) => { + const packageFile = getModuleInfo(packageName); + if (!packageFile) { + return; + } + packageMap.set(packageName, packageFile); + if (packageFile.type === "theme") { + themes.addTheme(packageName, packageFile); + } + + if (packageFile.onServerStart) { + packageFile.onServerStart(packageApis(packageName)); + } + }); + }); +} + +function getModuleInfo(packageName) { + let module; + try { + module = require(Helper.getPackageModulePath(packageName)); + } catch (e) { + log.warn(`Specified package ${colors.yellow(packageName)} is not installed in packages directory`); + return; + } + if (!module.thelounge) { + log.warn(`Specified package ${colors.yellow(packageName)} doesn't have required information.`); + return; + } + return module.thelounge; +} diff --git a/src/plugins/packages/themes.js b/src/plugins/packages/themes.js new file mode 100644 index 00000000..f6da6f5c --- /dev/null +++ b/src/plugins/packages/themes.js @@ -0,0 +1,66 @@ +"use strict"; + +const fs = require("fs"); +const Helper = require("../../helper"); +const path = require("path"); +const _ = require("lodash"); +const themes = new Map(); + +module.exports = { + addTheme, + getAll, + getFilename, + loadLocalThemes, +}; + +function loadLocalThemes() { + fs.readdir(path.join(__dirname, "..", "..", "public", "themes"), (err, builtInThemes) => { + if (err) { + return; + } + builtInThemes + .filter((theme) => theme.endsWith(".css")) + .map(makeLocalThemeObject) + .forEach((theme) => themes.set(theme.name, theme)); + }); +} + +function addTheme(packageName, packageObject) { + const theme = makePackageThemeObject(packageName, packageObject); + if (theme) { + themes.set(theme.name, theme); + } +} + +function getAll() { + return _.sortBy(Array.from(themes.values()), "displayName"); +} + +function getFilename(module) { + if (themes.has(module)) { + return themes.get(module).filename; + } +} + +function makeLocalThemeObject(css) { + const themeName = css.slice(0, -4); + return { + displayName: themeName.charAt(0).toUpperCase() + themeName.slice(1), + filename: path.join(__dirname, "..", "..", "public", "themes", `${themeName}.css`), + name: themeName, + }; +} + +function makePackageThemeObject(moduleName, module) { + if (!module || module.type !== "theme") { + return; + } + const modulePath = Helper.getPackageModulePath(moduleName); + const displayName = module.name || moduleName; + const filename = path.join(modulePath, module.css); + return { + displayName: displayName, + filename: filename, + name: moduleName, + }; +} diff --git a/src/plugins/themes.js b/src/plugins/themes.js deleted file mode 100644 index c56132f9..00000000 --- a/src/plugins/themes.js +++ /dev/null @@ -1,85 +0,0 @@ -"use strict"; - -const fs = require("fs"); -const Helper = require("../helper"); -const colors = require("colors/safe"); -const path = require("path"); -const _ = require("lodash"); -const themes = new Map(); - -module.exports = { - getAll: getAll, - getFilename: getFilename, -}; - -fs.readdir(path.join(__dirname, "..", "..", "public", "themes"), (err, builtInThemes) => { - if (err) { - return; - } - builtInThemes - .filter((theme) => theme.endsWith(".css")) - .map(makeLocalThemeObject) - .forEach((theme) => themes.set(theme.name, theme)); -}); - -fs.readdir(Helper.getPackagesPath(), (err, packages) => { - if (err) { - return; - } - packages - .map(makePackageThemeObject) - .forEach((theme) => { - if (theme) { - themes.set(theme.name, theme); - } - }); -}); - -function getAll() { - return _.sortBy(Array.from(themes.values()), "displayName"); -} - -function getFilename(module) { - if (themes.has(module)) { - return themes.get(module).filename; - } -} - -function makeLocalThemeObject(css) { - const themeName = css.slice(0, -4); - return { - displayName: themeName.charAt(0).toUpperCase() + themeName.slice(1), - filename: path.join(__dirname, "..", "..", "public", "themes", `${themeName}.css`), - name: themeName, - }; -} - -function getModuleInfo(packageName) { - let module; - try { - module = require(Helper.getPackageModulePath(packageName)); - } catch (e) { - log.warn(`Specified theme ${colors.yellow(packageName)} is not installed in packages directory`); - return; - } - if (!module.thelounge) { - log.warn(`Specified theme ${colors.yellow(packageName)} doesn't have required information.`); - return; - } - return module.thelounge; -} - -function makePackageThemeObject(moduleName) { - const module = getModuleInfo(moduleName); - if (!module || module.type !== "theme") { - return; - } - const modulePath = Helper.getPackageModulePath(moduleName); - const displayName = module.name || moduleName; - const filename = path.join(modulePath, module.css); - return { - displayName: displayName, - filename: filename, - name: moduleName, - }; -} diff --git a/src/server.js b/src/server.js index 6ec523ff..8e7e4bcf 100644 --- a/src/server.js +++ b/src/server.js @@ -13,9 +13,14 @@ var Helper = require("./helper"); var colors = require("colors/safe"); const net = require("net"); const Identification = require("./identification"); -const themes = require("./plugins/themes"); const changelog = require("./plugins/changelog"); +const themes = require("./plugins/packages/themes"); +themes.loadLocalThemes(); + +const packages = require("./plugins/packages/index"); +packages.loadPackages(); + // The order defined the priority: the first available plugin is used // ALways keep local auth in the end, which should always be enabled. const authPlugins = [ @@ -52,6 +57,17 @@ module.exports = function() { return res.sendFile(theme); }); + app.get("/packages/:package/:filename", (req, res) => { + const packageName = req.params.package; + const fileName = req.params.filename; + const packageFile = packages.getPackage(packageName); + if (!packageFile || !packages.getStylesheets().includes(`${packageName}/${fileName}`)) { + return res.status(404).send("Not found"); + } + const packagePath = Helper.getPackageModulePath(packageName); + return res.sendFile(path.join(packagePath, fileName)); + }); + var config = Helper.config; var server = null; @@ -235,7 +251,7 @@ function index(req, res, next) { throw err; } - res.send(_.template(file)(Helper.config)); + res.send(_.template(file)(getServerConfiguration())); }); } @@ -492,6 +508,14 @@ function getClientConfiguration() { return config; } +function getServerConfiguration() { + const config = _.clone(Helper.config); + + config.stylesheets = packages.getStylesheets(); + + return config; +} + function performAuthentication(data) { const socket = this; let client;