theme function (#73451)

This commit is contained in:
Peter Pisljar 2020-08-11 17:58:47 +02:00 committed by GitHub
parent 910c883607
commit 0ef17f92a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 73 deletions

View file

@ -64,7 +64,7 @@ export const font: ExpressionFunctionFont = {
inputTypes: ['null'],
args: {
align: {
default: 'left',
default: '{ theme "font.align" default="left" }',
help: i18n.translate('expressions.functions.font.args.alignHelpText', {
defaultMessage: 'The horizontal text alignment.',
}),
@ -72,13 +72,14 @@ export const font: ExpressionFunctionFont = {
types: ['string'],
},
color: {
default: `{ theme "font.color" }`,
help: i18n.translate('expressions.functions.font.args.colorHelpText', {
defaultMessage: 'The text color.',
}),
types: ['string'],
},
family: {
default: `"${openSans.value}"`,
default: `{ theme "font.family" default="${openSans.value}" }`,
help: i18n.translate('expressions.functions.font.args.familyHelpText', {
defaultMessage: 'An acceptable {css} web font string',
values: {
@ -88,7 +89,7 @@ export const font: ExpressionFunctionFont = {
types: ['string'],
},
italic: {
default: false,
default: `{ theme "font.italic" default=false }`,
help: i18n.translate('expressions.functions.font.args.italicHelpText', {
defaultMessage: 'Italicize the text?',
}),
@ -96,7 +97,7 @@ export const font: ExpressionFunctionFont = {
types: ['boolean'],
},
lHeight: {
default: null,
default: `{ theme "font.lHeight" }`,
aliases: ['lineHeight'],
help: i18n.translate('expressions.functions.font.args.lHeightHelpText', {
defaultMessage: 'The line height in pixels',
@ -104,14 +105,14 @@ export const font: ExpressionFunctionFont = {
types: ['number', 'null'],
},
size: {
default: 14,
default: `{ theme "font.size" default=14 }`,
help: i18n.translate('expressions.functions.font.args.sizeHelpText', {
defaultMessage: 'The font size in pixels',
}),
types: ['number'],
},
underline: {
default: false,
default: `{ theme "font.underline" default=false }`,
help: i18n.translate('expressions.functions.font.args.underlineHelpText', {
defaultMessage: 'Underline the text?',
}),
@ -119,7 +120,7 @@ export const font: ExpressionFunctionFont = {
types: ['boolean'],
},
weight: {
default: 'normal',
default: `{ theme "font.weight" default="normal" }`,
help: i18n.translate('expressions.functions.font.args.weightHelpText', {
defaultMessage: 'The font weight. For example, {list}, or {end}.',
values: {

View file

@ -24,6 +24,7 @@ import { kibanaContextFunction } from './kibana_context';
import { variableSet } from './var_set';
import { variable } from './var';
import { AnyExpressionFunctionDefinition } from '../types';
import { theme } from './theme';
export const functionSpecs: AnyExpressionFunctionDefinition[] = [
clog,
@ -32,6 +33,7 @@ export const functionSpecs: AnyExpressionFunctionDefinition[] = [
kibanaContextFunction,
variableSet,
variable,
theme,
];
export * from './clog';
@ -40,3 +42,4 @@ export * from './kibana';
export * from './kibana_context';
export * from './var_set';
export * from './var';
export * from './theme';

View file

@ -24,8 +24,19 @@ import { functionWrapper } from './utils';
describe('font', () => {
const fn = functionWrapper(font);
const args = {
align: 'left',
color: null,
family: openSans.value,
italic: false,
lHeight: null,
size: 14,
underline: false,
weight: 'normal',
};
describe('default output', () => {
const result = fn(null);
const result = fn(null, args);
it('returns a style', () => {
expect(result).toMatchObject({
@ -39,7 +50,7 @@ describe('font', () => {
describe('args', () => {
describe('size', () => {
it('sets font size', () => {
const result = fn(null, { size: 20 });
const result = fn(null, { ...args, size: 20 });
expect(result).toMatchObject({
spec: {
fontSize: '20px',
@ -47,21 +58,11 @@ describe('font', () => {
});
expect(result.css).toContain('font-size:20px');
});
it('defaults to 14px', () => {
const result = fn(null);
expect(result).toMatchObject({
spec: {
fontSize: '14px',
},
});
expect(result.css).toContain('font-size:14px');
});
});
describe('lHeight', () => {
it('sets line height', () => {
const result = fn(null, { lHeight: 30 });
const result = fn(null, { ...args, lHeight: 30 });
expect(result).toMatchObject({
spec: {
lineHeight: '30px',
@ -69,31 +70,19 @@ describe('font', () => {
});
expect(result.css).toContain('line-height:30px');
});
it('defaults to 1', () => {
const result = fn(null);
expect(result.spec.lineHeight).toBe('1');
expect(result.css).toContain('line-height:1');
});
});
describe('family', () => {
it('sets font family', () => {
const result = fn(null, { family: 'Optima, serif' });
const result = fn(null, { ...args, family: 'Optima, serif' });
expect(result.spec.fontFamily).toBe('Optima, serif');
expect(result.css).toContain('font-family:Optima, serif');
});
it(`defaults to "${openSans.value}"`, () => {
const result = fn(null);
expect(result.spec.fontFamily).toBe(`"${openSans.value}"`);
expect(result.css).toContain(`font-family:"${openSans.value}"`);
});
});
describe('color', () => {
it('sets font color', () => {
const result = fn(null, { color: 'blue' });
const result = fn(null, { ...args, color: 'blue' });
expect(result.spec.color).toBe('blue');
expect(result.css).toContain('color:blue');
});
@ -101,51 +90,39 @@ describe('font', () => {
describe('weight', () => {
it('sets font weight', () => {
let result = fn(null, { weight: 'normal' });
let result = fn(null, { ...args, weight: 'normal' });
expect(result.spec.fontWeight).toBe('normal');
expect(result.css).toContain('font-weight:normal');
result = fn(null, { weight: 'bold' });
result = fn(null, { ...args, weight: 'bold' });
expect(result.spec.fontWeight).toBe('bold');
expect(result.css).toContain('font-weight:bold');
result = fn(null, { weight: 'bolder' });
result = fn(null, { ...args, weight: 'bolder' });
expect(result.spec.fontWeight).toBe('bolder');
expect(result.css).toContain('font-weight:bolder');
result = fn(null, { weight: 'lighter' });
result = fn(null, { ...args, weight: 'lighter' });
expect(result.spec.fontWeight).toBe('lighter');
expect(result.css).toContain('font-weight:lighter');
result = fn(null, { weight: '400' });
result = fn(null, { ...args, weight: '400' });
expect(result.spec.fontWeight).toBe('400');
expect(result.css).toContain('font-weight:400');
});
it("defaults to 'normal'", () => {
const result = fn(null);
expect(result.spec.fontWeight).toBe('normal');
expect(result.css).toContain('font-weight:normal');
});
it('throws when provided an invalid weight', () => {
expect(() => fn(null, { weight: 'foo' })).toThrow();
expect(() => fn(null, { ...args, weight: 'foo' })).toThrow();
});
});
describe('underline', () => {
it('sets text underline', () => {
let result = fn(null, { underline: true });
let result = fn(null, { ...args, underline: true });
expect(result.spec.textDecoration).toBe('underline');
expect(result.css).toContain('text-decoration:underline');
result = fn(null, { underline: false });
expect(result.spec.textDecoration).toBe('none');
expect(result.css).toContain('text-decoration:none');
});
it('defaults to false', () => {
const result = fn(null);
result = fn(null, { ...args, underline: false });
expect(result.spec.textDecoration).toBe('none');
expect(result.css).toContain('text-decoration:none');
});
@ -153,17 +130,11 @@ describe('font', () => {
describe('italic', () => {
it('sets italic', () => {
let result = fn(null, { italic: true });
let result = fn(null, { ...args, italic: true });
expect(result.spec.fontStyle).toBe('italic');
expect(result.css).toContain('font-style:italic');
result = fn(null, { italic: false });
expect(result.spec.fontStyle).toBe('normal');
expect(result.css).toContain('font-style:normal');
});
it('defaults to false', () => {
const result = fn(null);
result = fn(null, { ...args, italic: false });
expect(result.spec.fontStyle).toBe('normal');
expect(result.css).toContain('font-style:normal');
});
@ -171,31 +142,25 @@ describe('font', () => {
describe('align', () => {
it('sets text alignment', () => {
let result = fn(null, { align: 'left' });
let result = fn(null, { ...args, align: 'left' });
expect(result.spec.textAlign).toBe('left');
expect(result.css).toContain('text-align:left');
result = fn(null, { align: 'center' });
result = fn(null, { ...args, align: 'center' });
expect(result.spec.textAlign).toBe('center');
expect(result.css).toContain('text-align:center');
result = fn(null, { align: 'right' });
result = fn(null, { ...args, align: 'right' });
expect(result.spec.textAlign).toBe('right');
expect(result.css).toContain('text-align:right');
result = fn(null, { align: 'justify' });
result = fn(null, { ...args, align: 'justify' });
expect(result.spec.textAlign).toBe('justify');
expect(result.css).toContain('text-align:justify');
});
it(`defaults to 'left'`, () => {
const result = fn(null);
expect(result.spec.textAlign).toBe('left');
expect(result.css).toContain('text-align:left');
});
it('throws when provided an invalid alignment', () => {
expect(() => fn(null, { align: 'foo' })).toThrow();
expect(() => fn(null, { ...args, align: 'foo' })).toThrow();
});
});
});

View file

@ -0,0 +1,63 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { functionWrapper } from './utils';
import { theme } from '../theme';
import { ExecutionContext } from '../../../execution/types';
describe('expression_functions', () => {
describe('theme', () => {
const fn = functionWrapper(theme);
let context: ExecutionContext;
let themeProps;
beforeEach(() => {
themeProps = {
font: {
family: 'Arial',
size: 14,
},
};
context = {
getInitialInput: () => {},
types: {},
variables: { theme: themeProps },
abortSignal: {} as any,
inspectorAdapters: {} as any,
};
});
it('returns the selected variable', () => {
const actual = fn(null, { variable: 'font.family' }, context);
expect(actual).toEqual('Arial');
});
it('returns undefined if variable does not exist', () => {
const actual = fn(null, { variable: 'font.weight' }, context);
expect(actual).toEqual(undefined);
});
it('returns default if variable does not exist and default is provided', () => {
const actual = fn(null, { variable: 'font.weight', default: 'normal' }, context);
expect(actual).toEqual('normal');
});
});
});

View file

@ -0,0 +1,65 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { ExpressionFunctionDefinition } from '../types';
interface Arguments {
variable: string;
default: string | number | boolean;
}
type Output = any;
export type ExpressionFunctionTheme = ExpressionFunctionDefinition<
'theme',
null,
Arguments,
Output
>;
export const theme: ExpressionFunctionTheme = {
name: 'theme',
aliases: [],
help: i18n.translate('expressions.functions.themeHelpText', {
defaultMessage: 'Reads a theme setting.',
}),
inputTypes: ['null'],
args: {
variable: {
aliases: ['_'],
help: i18n.translate('expressions.functions.theme.args.variableHelpText', {
defaultMessage: 'Name of the theme variable to read.',
}),
required: true,
types: ['string'],
},
default: {
help: i18n.translate('expressions.functions.theme.args.defaultHelpText', {
defaultMessage: 'default value in case theming info is not available.',
}),
},
},
fn: (input, args, handlers) => {
// currently we use variable `theme`, but external theme service would be preferable
const vars = handlers.variables.theme || {};
return get(vars, args.variable, args.default);
},
};

View file

@ -28,6 +28,7 @@ import {
ExpressionFunctionKibana,
ExpressionFunctionVarSet,
ExpressionFunctionVar,
ExpressionFunctionTheme,
} from './specs';
/**
@ -122,4 +123,5 @@ export interface ExpressionFunctionDefinitions {
kibana: ExpressionFunctionKibana;
var_set: ExpressionFunctionVarSet;
var: ExpressionFunctionVar;
theme: ExpressionFunctionTheme;
}