@@ -1,6 +1,12 @@
 const Setting = require('lib/models/Setting.js');
+const lightStyle = require('./gui/style/theme/light'); // Default theme
+const darkStyle = require('./gui/style/theme/dark');
+const draculaStyle = require('./gui/style/theme/dracula');
+const solarizedLightStyle = require('./gui/style/theme/solarizedLight');
+const solarizedDarkStyle = require('./gui/style/theme/solarizedDark');
 const nordStyle = require('./gui/style/theme/nord');
 
+
 // globalStyle should be used for properties that do not change across themes
 // i.e. should not be used for colors
 const globalStyle = {
const Setting = require('lib/models/Setting.js');
const nordStyle = require('./gui/style/theme/nord');

// globalStyle should be used for properties that do not change across themes
// i.e. should not be used for colors
const globalStyle = {
	fontSize: 12,
	fontFamily: 'sans-serif',
	margin: 15, // No text and no interactive component should be within this margin
	itemMarginTop: 10,
	itemMarginBottom: 10,
	fontSizeSmaller: 14,
	disabledOpacity: 0.3,
	buttonMinWidth: 50,
	buttonMinHeight: 30,
	editorFontSize: 12,
	textAreaLineHeight: 17,

	headerHeight: 35,
	headerButtonHPadding: 6,

	toolbarHeight: 35,
	tagItemPadding: 3,
};

globalStyle.marginRight = globalStyle.margin;
globalStyle.marginLeft = globalStyle.margin;
globalStyle.marginTop = globalStyle.margin;
globalStyle.marginBottom = globalStyle.margin;
globalStyle.htmlMarginLeft = `${((globalStyle.marginLeft / 10) * 0.6).toFixed(2)}em`;

globalStyle.icon = {
	fontSize: 30,
};

globalStyle.lineInput = {
	fontFamily: globalStyle.fontFamily,
	maxHeight: 22,
	height: 22,
	paddingLeft: 5,
};

globalStyle.headerStyle = {
	fontFamily: globalStyle.fontFamily,
};

globalStyle.inputStyle = {
	border: '1px solid',
	height: 24,
	maxHeight: 24,
	paddingLeft: 5,
	paddingRight: 5,
	boxSizing: 'border-box',
};

globalStyle.containerStyle = {
	overflow: 'auto',
	overflowY: 'auto',
};

globalStyle.buttonStyle = {
	// marginRight: 10,
	border: '1px solid',
	minHeight: 26,
	minWidth: 80,
	// maxWidth: 220,
	paddingLeft: 12,
	paddingRight: 12,
	paddingTop: 6,
	paddingBottom: 6,
	boxShadow: '0px 1px 1px rgba(0,0,0,0.3)',
	fontSize: globalStyle.fontSize,
	borderRadius: 4,
};

const lightStyle = {
	backgroundColor: '#ffffff',
	backgroundColorTransparent: 'rgba(255,255,255,0.9)',
	oddBackgroundColor: '#dddddd',
	color: '#222222', // For regular text
	colorError: 'red',
	colorWarn: '#9A5B00',
	colorFaded: '#777777', // For less important text
	colorBright: '#000000', // For important text
	dividerColor: '#dddddd',
	selectedColor: '#e5e5e5',
	urlColor: '#155BDA',

	backgroundColor2: '#162B3D',
	depthColor: 'rgb(100, 182, 253, OPACITY)',
	color2: '#f5f5f5',
	selectedColor2: '#0269C2',
	colorError2: '#ff6c6c',

	raisedBackgroundColor: '#e5e5e5',
	raisedColor: '#222222',

	warningBackgroundColor: '#FFD08D',

	htmlColor: '#222222',
	htmlBackgroundColor: 'white',
	htmlDividerColor: 'rgb(230,230,230)',
	htmlLinkColor: 'rgb(80,130,190)',
	htmlTableBackgroundColor: 'rgb(247, 247, 247)',
	htmlCodeBackgroundColor: 'rgb(243, 243, 243)',
	htmlCodeBorderColor: 'rgb(220, 220, 220)',
	htmlCodeColor: 'rgb(0,0,0)',

	editorTheme: 'chrome',
	codeThemeCss: 'atom-one-light.css',
};

const darkStyle = {
	backgroundColor: '#1D2024',
	backgroundColorTransparent: 'rgba(255,255,255,0.9)',
	oddBackgroundColor: '#dddddd',
	color: '#dddddd',
	colorError: 'red',
	colorWarn: '#9A5B00',
	colorFaded: '#777777', // For less important text
	colorBright: '#ffffff', // For important text
	dividerColor: '#555555',
	selectedColor: '#333333',
	urlColor: '#4E87EE',

	backgroundColor2: '#181A1D',
	depthColor: 'rgb(200, 200, 200, OPACITY)',
	color2: '#ffffff',
	selectedColor2: '#013F74',
	colorError2: '#ff6c6c',

	raisedBackgroundColor: '#474747',
	raisedColor: '#ffffff',

	warningBackgroundColor: '#CC6600',

	htmlColor: 'rgb(220,220,220)',
	htmlBackgroundColor: 'rgb(29,32,36)',
	htmlDividerColor: '#3D444E',
	htmlCodeColor: '#ffffff',
	htmlLinkColor: 'rgb(166,166,255)',
	htmlTableBackgroundColor: 'rgb(40, 41, 42)',
	htmlCodeBackgroundColor: 'rgb(47, 48, 49)',
	htmlCodeBorderColor: 'rgb(70, 70, 70)',

	editorTheme: 'twilight',
	codeThemeCss: 'atom-one-dark-reasonable.css',

	highlightedColor: '#0066C7',
};

// Solarized Styles
const solarizedLightStyle = {
	backgroundColor: '#fdf6e3',
	backgroundColorTransparent: 'rgba(253, 246, 227, 0.9)',
	oddBackgroundColor: '#eee8d5',
	color: '#657b83', // For regular text
	colorError: '#dc322f',
	colorWarn: '#cb4b16',
	colorFaded: '#839496', // For less important text;
	colorBright: '#073642', // For important text;
	dividerColor: '#eee8d5',
	selectedColor: '#eee8d5',
	urlColor: '#268bd2',

	backgroundColor2: '#002b36',
	depthColor: 'rgb(100, 182, 253, OPACITY)',
	color2: '#eee8d5',
	selectedColor2: '#6c71c4',
	colorError2: '#cb4b16',

	raisedBackgroundColor: '#eee8d5',
	raisedColor: '#073642',

	warningBackgroundColor: '#b5890055',

	htmlColor: '#657b83',
	htmlBackgroundColor: '#fdf6e3',
	htmlDividerColor: '#eee8d5',
	htmlLinkColor: '#268bd2',
	htmlTableBackgroundColor: '#fdf6e3',
	htmlCodeBackgroundColor: '#fdf6e3',
	htmlCodeBorderColor: '#eee8d5',
	htmlCodeColor: '#002b36',

	editorTheme: 'solarized_light',
	codeThemeCss: 'atom-one-light.css',
};

const solarizedDarkStyle = {
	backgroundColor: '#002b36',
	backgroundColorTransparent: 'rgba(0, 43, 54, 0.9)',
	oddBackgroundColor: '#073642',
	color: '#93a1a1', // For regular text
	colorError: '#dc322f',
	colorWarn: '#cb4b16',
	colorFaded: '#657b83', // For less important text;
	colorBright: '#eee8d5', // For important text;
	dividerColor: '#586e75',
	selectedColor: '#073642',
	urlColor: '#268bd2',

	backgroundColor2: '#073642',
	depthColor: 'rgb(200, 200, 200, OPACITY)',
	color2: '#eee8d5',
	selectedColor2: '#6c71c4',
	colorError2: '#cb4b16',

	raisedBackgroundColor: '#073642',
	raisedColor: '#839496',

	warningBackgroundColor: '#b5890055',

	htmlColor: '#93a1a1',
	htmlBackgroundColor: '#002b36',
	htmlDividerColor: '#073642',
	htmlLinkColor: '#268bd2',
	htmlTableBackgroundColor: '#002b36',
	htmlCodeBackgroundColor: '#002b36',
	htmlCodeBorderColor: '#696969',
	htmlCodeColor: '#fdf6e3',

	editorTheme: 'solarized_dark',
	codeThemeCss: 'atom-one-dark-reasonable.css',
};

const draculaStyle = {
	backgroundColor: '#282a36',
	backgroundColorTransparent: 'rgba(40, 42, 54, 0.9)',
	oddBackgroundColor: '#282a36',
	color: '#f8f8f2', // For regular text
	colorError: '#ff5555',
	colorWarn: '#ffb86c',
	colorFaded: '#6272a4', // For less important text;
	colorBright: '#50fa7b', // For important text;
	dividerColor: '#bd93f9',
	selectedColor: '#44475a',
	urlColor: '#8be9fd',

	backgroundColor2: '#21222C',
	depthColor: 'rgb(200, 200, 200, OPACITY)',
	color2: '#bd93f9',
	selectedColor2: '#44475a',
	colorError2: '#ff5555',

	raisedBackgroundColor: '#44475a',
	raisedColor: '#bd93f9',

	warningBackgroundColor: '#ffb86c',

	htmlColor: '#f8f8f2',
	htmlBackgroundColor: '#282a36',
	htmlDividerColor: '#f8f8f2',
	htmlLinkColor: '#8be9fd',
	htmlTableBackgroundColor: '#6272a4',
	htmlCodeBackgroundColor: '#44475a',
	htmlCodeBorderColor: '#f8f8f2',
	htmlCodeColor: '#50fa7b',

	editorTheme: 'dracula',
	codeThemeCss: 'atom-one-dark-reasonable.css',
};

function addExtraStyles(style) {
	style.tagStyle = {
		fontSize: style.fontSize,
		fontFamily: style.fontFamily,
		marginTop: style.itemMarginTop * 0.4,
		marginBottom: style.itemMarginBottom * 0.4,
		marginRight: style.margin * 0.3,
		paddingTop: style.tagItemPadding,
		paddingBottom: style.tagItemPadding,
		paddingRight: style.tagItemPadding * 2,
		paddingLeft: style.tagItemPadding * 2,
		backgroundColor: style.raisedBackgroundColor,
		color: style.raisedColor,
	};

	style.toolbarStyle = {
		height: style.toolbarHeight,
		// minWidth: style.toolbarHeight,
		display: 'flex',
		alignItems: 'center',
		paddingLeft: style.headerButtonHPadding,
		paddingRight: style.headerButtonHPadding,
		textDecoration: 'none',
		fontFamily: style.fontFamily,
		fontSize: style.fontSize,
		boxSizing: 'border-box',
		cursor: 'default',
		justifyContent: 'center',
		color: style.color,
		whiteSpace: 'nowrap',
	};

	style.textStyle = {
		fontFamily: globalStyle.fontFamily,
		fontSize: style.fontSize,
		lineHeight: '1.6em',
		color: style.color,
	};

	style.textStyle2 = Object.assign({}, style.textStyle,
		{ color: style.color2 }
	);

	style.urlStyle = Object.assign({}, style.textStyle,
		{
			textDecoration: 'underline',
			color: style.urlColor,
		}
	);

	style.h1Style = Object.assign({},
		style.textStyle,
		{
			color: style.color,
			fontSize: style.textStyle.fontSize * 1.5,
			fontWeight: 'bold',
		}
	);

	style.h2Style = Object.assign({},
		style.textStyle,
		{
			color: style.color,
			fontSize: style.textStyle.fontSize * 1.3,
			fontWeight: 'bold',
		}
	);

	style.dialogModalLayer = {
		zIndex: 9999,
		display: 'flex',
		position: 'absolute',
		top: 0,
		left: 0,
		width: '100%',
		height: '100%',
		backgroundColor: 'rgba(0,0,0,0.6)',
		alignItems: 'flex-start',
		justifyContent: 'center',
	};

	style.controlBox = {
		marginBottom: '1em',
		color: 'black', // This will apply for the calendar
		display: 'flex',
		flexDirection: 'row',
		alignItems: 'center',
	};

	style.controlBoxLabel = {
		marginRight: '1em',
		width: '10em',
		display: 'inline-block',
		fontWeight: 'bold',
	};

	style.controlBoxValue = {
		display: 'inline-block',
	};

	style.dialogBox = {
		backgroundColor: style.backgroundColor,
		padding: 16,
		boxShadow: '6px 6px 20px rgba(0,0,0,0.5)',
		marginTop: 20,
	};

	style.buttonIconStyle = {
		color: style.color,
		marginRight: 6,
	};

	style.dialogTitle = Object.assign({}, style.h1Style, { marginBottom: '1.2em' });

	style.dropdownList = Object.assign({}, style.inputStyle);

	// In general the highlighted color, used to highlight text or icons, should be the same as selectedColor2
	// but some times, depending on the theme, it might be too dark or too light, so it can be
	// specified directly by the theme too.
	if (!style.highlightedColor) style.highlightedColor = style.selectedColor2;

	return style;
}

const themeCache_ = {};

function themeStyle(theme) {
	if (!theme) throw new Error('Theme must be specified');

	const zoomRatio = 1; // Setting.value('style.zoom') / 100;
	const editorFontSize = Setting.value('style.editor.fontSize');

	const cacheKey = [theme, zoomRatio, editorFontSize].join('-');
	if (themeCache_[cacheKey]) return themeCache_[cacheKey];

	// Font size are not theme specific, but they must be referenced
	// and computed here to allow them to respond to settings changes
	// without the need to restart
	const fontSizes = {
		fontSize: Math.round(globalStyle.fontSize * zoomRatio),
		editorFontSize: editorFontSize,
		textAreaLineHeight: Math.round(globalStyle.textAreaLineHeight * editorFontSize / 12),

		// For WebView - must correspond to the properties above
		htmlFontSize: `${Math.round(15 * zoomRatio)}px`,
		htmlLineHeight: '1.6em', // Math.round(20 * zoomRatio) + 'px'

		htmlCodeFontSize: '.9em',
	};

	let output = {};
	output.zoomRatio = zoomRatio;
	output.editorFontSize = editorFontSize;

	// All theme are based on the light style, and just override the
	// relevant properties
	output = Object.assign({}, globalStyle, fontSizes, lightStyle);

	switch (theme) {
	case Setting.THEME_DARK :
		output = Object.assign({}, output, darkStyle); break;
	case Setting.THEME_SOLARIZED_LIGHT :
		output = Object.assign({}, output, solarizedLightStyle); break;
	case Setting.THEME_SOLARIZED_DARK :
		output = Object.assign({}, output, solarizedDarkStyle); break;
	case Setting.THEME_DRACULA :
		output = Object.assign({}, output, draculaStyle); break;
	case Setting.THEME_NORD :
		output = Object.assign({}, output, nordStyle); break;
	}

	// Note: All the theme specific things should go in addExtraStyles
	// so that their definition is not split between here and the
	// beginning of the file. At least new styles should go in
	// addExtraStyles.

	output.icon = Object.assign({},
		output.icon,
		{ color: output.color }
	);

	output.lineInput = Object.assign({},
		output.lineInput,
		{
			color: output.color,
			backgroundColor: output.backgroundColor,
		}
	);

	output.headerStyle = Object.assign({},
		output.headerStyle,
		{
			color: output.color,
			backgroundColor: output.backgroundColor,
		}
	);

	output.inputStyle = Object.assign({},
		output.inputStyle,
		{
			color: output.color,
			backgroundColor: output.backgroundColor,
			borderColor: output.dividerColor,
		}
	);

	output.containerStyle = Object.assign({},
		output.containerStyle,
		{
			color: output.color,
			backgroundColor: output.backgroundColor,
		}
	);

	output.buttonStyle = Object.assign({},
		output.buttonStyle,
		{
			color: output.color,
			backgroundColor: output.backgroundColor,
			borderColor: output.dividerColor,
		}
	);

	output = addExtraStyles(output);

	themeCache_[cacheKey] = output;
	return themeCache_[cacheKey];
}

const cachedStyles_ = {};

function buildStyle(cacheKey, themeId, callback) {
	if (cachedStyles_[cacheKey]) cachedStyles_[cacheKey].style;

	const s = callback(themeStyle(themeId));

	cachedStyles_[cacheKey] = {
		style: s,
		timestamp: Date.now(),
	};

	return cachedStyles_[cacheKey].style;
}

module.exports = { themeStyle, buildStyle };

How about moving all these themes under a `themes` object? Like `const themes = {[Setting.THEME_LIGHT]: require('./gui/style/theme/light'), ...` That will make it easier to add new theme and we'll automatically have the mapping theme ID to module.