Merge pull request #1619 from thelounge/1447-css-plugin

Allow custom css from plugins
This commit is contained in:
Jérémie Astori 2018-01-10 21:44:47 -05:00 committed by GitHub
commit 40aadf7c95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 167 additions and 87 deletions

View file

@ -11,6 +11,9 @@
<link rel="stylesheet" href="css/primer-tooltips.css">
<link rel="stylesheet" href="css/style.css">
<link id="theme" rel="stylesheet" href="<%- theme %>">
<% _.forEach(stylesheets, function(css) { %>
<link rel="stylesheet" href="/packages/<%- css %>">
<% }); %>
<style id="user-specified-css"></style>
<title>The Lounge</title>

View file

@ -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;
}

View file

@ -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,
};
}

View file

@ -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,
};
}

View file

@ -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;