Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS themes and convert themes #1047

Merged
merged 4 commits into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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