Skip to content

Commit

Permalink
JS themes and convert themes (#1047)
Browse files Browse the repository at this point in the history
* JS themes and convert themes

* Publish

 - [email protected]
 - [email protected]

* Publish

 - [email protected]
 - [email protected]

* Publish

 - [email protected]
 - [email protected]
  • Loading branch information
gschier authored Jul 17, 2018
1 parent c7dae0c commit 5ad79f3
Show file tree
Hide file tree
Showing 52 changed files with 1,224 additions and 745 deletions.
19 changes: 18 additions & 1 deletion packages/insomnia-app/app/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PLUGIN_PATH } from '../common/constants';
import { resolveHomePath } from '../common/misc';
import { showError } from '../ui/components/modals/index';
import type { PluginTemplateTag } from '../templating/extensions/index';
import type { PluginTheme } from './misc';

export type Plugin = {
name: string,
Expand All @@ -31,6 +32,11 @@ export type ResponseHook = {
hook: Function
};

export type Theme = {
plugin: Plugin,
theme: PluginTheme
};

const CORE_PLUGINS = [
'insomnia-plugin-base64',
'insomnia-plugin-hash',
Expand All @@ -40,7 +46,8 @@ const CORE_PLUGINS = [
'insomnia-plugin-prompt',
'insomnia-plugin-request',
'insomnia-plugin-response',
'insomnia-plugin-jsonpath'
'insomnia-plugin-jsonpath',
'insomnia-plugin-core-themes'
];

let plugins: ?Array<Plugin> = null;
Expand Down Expand Up @@ -193,6 +200,16 @@ export async function getResponseHooks(): Promise<Array<ResponseHook>> {
return functions;
}

export async function getThemes(): Promise<Array<Theme>> {
let extensions = [];
for (const plugin of await getPlugins()) {
const themes = plugin.module.themes || [];
extensions = [...extensions, ...themes.map(theme => ({ plugin, theme }))];
}

return extensions;
}

function _initPlugin(packageJSON: Object, module: any, path: ?string): Plugin {
const meta = packageJSON.insomnia || {};
return {
Expand Down
256 changes: 256 additions & 0 deletions packages/insomnia-app/app/plugins/misc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
// @flow
import { render, THROW_ON_ERROR } from '../common/render';
import { getThemes } from './index';

type ThemeBlock = {
background?: {
default: string,
success?: string,
notice?: string,
warning?: string,
danger?: string,
surprise?: string,
info?: string
},
foreground?: {
default: string,
success?: string,
notice?: string,
warning?: string,
danger?: string,
surprise?: string,
info?: string
},
highlight?: {
default: string,
xxs?: string,
xs?: string,
sm?: string,
md?: string,
lg?: string,
xl?: string
}
};

type ThemeInner = {
...ThemeBlock,
styles: ?{
overlay?: ThemeBlock,
dropdown?: ThemeBlock,
tooltip?: ThemeBlock,
sidebar?: ThemeBlock,
sidebarHeader?: ThemeBlock,
sidebarList?: ThemeBlock,
sidebarActions?: ThemeBlock,
pane?: ThemeBlock,
paneHeader?: ThemeBlock,
dialog?: ThemeBlock,
dialogHeader?: ThemeBlock,
dialogFooter?: ThemeBlock,
transparentOverlay?: ThemeBlock,
link?: ThemeBlock
}
};

export type PluginTheme = {
name: string,
displayName: string,
theme: ThemeInner
};

export async function generateThemeCSS(theme: PluginTheme): Promise<string> {
const renderedTheme: ThemeInner = await render(
theme.theme,
theme.theme,
null,
THROW_ON_ERROR,
theme.name
);
const n = theme.name;

let css = '';
css += wrapStyles(n, '', getThemeBlockCSS(renderedTheme));

if (renderedTheme.styles) {
const styles = renderedTheme.styles;

// Dropdown Menus
css += wrapStyles(
n,
'.theme--dropdown__menu',
getThemeBlockCSS(styles.dialog)
);
css += wrapStyles(
n,
'.theme--dropdown__menu',
getThemeBlockCSS(styles.dropdown)
);

// Tooltips
css += wrapStyles(n, '.theme--tooltip', getThemeBlockCSS(styles.dialog));
css += wrapStyles(n, '.theme--tooltip', getThemeBlockCSS(styles.tooltip));

// Overlay
css += wrapStyles(
n,
'.theme--transparent-overlay',
getThemeBlockCSS(styles.transparentOverlay)
);

// Dialogs
css += wrapStyles(n, '.theme--dialog', getThemeBlockCSS(styles.dialog));
css += wrapStyles(
n,
'.theme--dialog__header',
getThemeBlockCSS(styles.dialogHeader)
);
css += wrapStyles(
n,
'.theme--dialog__footer',
getThemeBlockCSS(styles.dialogFooter)
);

// Panes
css += wrapStyles(n, '.theme--pane', getThemeBlockCSS(styles.pane));
css += wrapStyles(
n,
'.theme--pane__header',
getThemeBlockCSS(styles.paneHeader)
);

// Sidebar Styles
css += wrapStyles(n, '.theme--sidebar', getThemeBlockCSS(styles.sidebar));
css += wrapStyles(
n,
'.theme--sidebar__list',
getThemeBlockCSS(styles.sidebarList)
);
css += wrapStyles(
n,
'.theme--sidebar__actions',
getThemeBlockCSS(styles.sidebarActions)
);
css += wrapStyles(
n,
'.theme--sidebar__header',
getThemeBlockCSS(styles.sidebarHeader)
);

// Link
css += wrapStyles(n, '.theme--link', getThemeBlockCSS(styles.link));

// HACK: Dialog styles for CodeMirror dialogs too
css += wrapStyles(n, '.CodeMirror-info', getThemeBlockCSS(styles.dialog));
}

return css;
}

function getThemeBlockCSS(block?: ThemeBlock): string {
if (!block) {
return '';
}

const indent = '\t';

let css = '';

const addVar = (variable?: string, value?: string) => {
if (variable && value) {
css += `${indent}--${variable}: ${value};\n`;
}
};

const addComment = comment => {
css += `${indent}/* ${comment} */\n`;
};

const addNewLine = () => {
css += `\n`;
};

if (block.background) {
const { background } = block;
addComment('Background');
addVar('color-bg', background.default);
addVar('color-success', background.success);
addVar('color-notice', background.notice);
addVar('color-warning', background.warning);
addVar('color-danger', background.danger);
addVar('color-surprise', background.surprise);
addVar('color-info', background.info);
addNewLine();
}

if (block.foreground) {
const { foreground } = block;
addComment('Foreground');
addVar('color-font', foreground.default);
addVar('color-font-success', foreground.success);
addVar('color-font-notice', foreground.notice);
addVar('color-font-warning', foreground.warning);
addVar('color-font-danger', foreground.danger);
addVar('color-font-surprise', foreground.surprise);
addVar('color-font-info', foreground.info);
addNewLine();
}

if (block.highlight) {
const { highlight } = block;
addComment('Highlight');
addVar('hl', highlight.default);
addVar('hl-xxs', highlight.xxs);
addVar('hl-xs', highlight.xs);
addVar('hl-sm', highlight.sm);
addVar('hl-md', highlight.md);
addVar('hl-lg', highlight.lg);
addVar('hl-xl', highlight.xl);
addNewLine();
}

return css.replace(/\s+$/, '');
}

function wrapStyles(theme: string, selector: string, styles: string) {
if (!styles) {
return '';
}

return [
`[theme="${theme}"] ${selector}, `,
`[subtheme="${theme}"] ${selector ? selector + '--sub' : ''} {`,
styles,
'}',
'',
''
].join('\n');
}

export async function setThemes() {
if (!document) {
return;
}

const head = document.head;

if (!head) {
return;
}

const themes = await getThemes();

for (const theme of themes) {
const themeCSS = (await generateThemeCSS(theme.theme)) + '\n';

let s = document.querySelector(
`style[data-theme-name="${theme.theme.name}"]`
);
if (!s) {
s = document.createElement('style');
s.setAttribute('data-theme-name', theme.theme.name);
head.appendChild(s);
}

s.innerHTML = themeCSS;
}
}
5 changes: 4 additions & 1 deletion packages/insomnia-app/app/templating/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ let nunjucksAll = null;
* @param {Object} [config.path] - Path to include in the error message
* @param {Object} [config.renderMode] - Only render variables (not tags)
*/
export function render(text: string, config: Object = {}): Promise<string> {
export function render(
text: string,
config: { context?: Object, path?: string, renderMode?: string } = {}
): Promise<string> {
const context = config.context || {};
const path = config.path || null;
const renderMode = config.renderMode || RENDER_ALL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ class Dropdown extends PureComponent {
if (!container) {
container = document.createElement('div');
container.id = 'dropdowns-container';
container.style.zIndex = '1000000';
container.style.position = 'relative';
document.body.appendChild(container);
}

Expand Down Expand Up @@ -382,7 +384,7 @@ class Dropdown extends PureComponent {
finalChildren = [
dropdownButtons[0],
<div key="item" className={menuClasses} ref={this._addDropdownMenuRef}>
<div className="dropdown__backdrop theme--overlay" />
<div className="dropdown__backdrop theme--transparent-overlay" />
<div
key={uniquenessKey}
ref={this._addDropdownListRef}
Expand Down
2 changes: 1 addition & 1 deletion packages/insomnia-app/app/ui/components/base/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Link extends React.PureComponent<Props> {
<a
href={href}
onClick={this._handleClick}
className={className}
className={(className || '') + ' theme--link'}
{...other}>
{children}
</a>
Expand Down
2 changes: 1 addition & 1 deletion packages/insomnia-app/app/ui/components/base/modal-body.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import classnames from 'classnames';
class ModalBody extends PureComponent {
render() {
const { className, children, noScroll, ...props } = this.props;
const classes = classnames(className, 'modal__body', {
const classes = classnames(className, 'modal__body theme--dialog__body', {
'modal__body--no-scroll': noScroll
});

Expand Down
8 changes: 7 additions & 1 deletion packages/insomnia-app/app/ui/components/base/modal-footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ class ModalFooter extends PureComponent {
render() {
const { children, className } = this.props;
return (
<div className={classnames('modal__footer', className)}>{children}</div>
<div
className={classnames(
'modal__footer theme--dialog__footer',
className
)}>
{children}
</div>
);
}
}
Expand Down
6 changes: 5 additions & 1 deletion packages/insomnia-app/app/ui/components/base/modal-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ class ModalHeader extends PureComponent {
}

return (
<div className={classnames('modal__header', className)}>
<div
className={classnames(
'modal__header theme--dialog__header',
className
)}>
<div className="modal__header__children">{children}</div>
{closeButton}
</div>
Expand Down
3 changes: 2 additions & 1 deletion packages/insomnia-app/app/ui/components/base/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Modal extends PureComponent {

const classes = classnames(
'modal',
'theme--dialog',
className,
{ 'modal--fixed-height': tall },
{ 'modal--noescape': noEscape },
Expand All @@ -141,7 +142,7 @@ class Modal extends PureComponent {
style={styles}
onClick={this._handleClick}>
<div
className="modal__backdrop overlay theme--overlay"
className="modal__backdrop overlay theme--transparent-overlay"
data-close-modal
/>
<div className="modal__content__wrapper">
Expand Down
Loading

0 comments on commit 5ad79f3

Please sign in to comment.