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;