chore: page 的 style 里针对 backgroundImage 自动加上 url (#3581)

This commit is contained in:
吴多益 2022-02-15 16:23:46 +08:00 committed by GitHub
parent 2a5fbc588c
commit 97820a1075
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 158 additions and 42 deletions

23
__mocks__/monaco.ts Normal file
View File

@ -0,0 +1,23 @@
/**
* monaco mock
*/
export const languages = {
register: function (language: any) {},
setMonarchTokensProvider: function (name: any, tokens: any) {},
registerCompletionItemProvider: function (name: any, provider: any) {}
};
export const editor = {
defineTheme: function (name: any, theme: any) {},
create: function (name: any, theme: any) {
return {
onDidChangeModelDecorations: () => {
return {
dispose: () => {}
};
},
dispose: () => {}
};
}
};

View File

@ -4,7 +4,6 @@ exports[`Renderer:Page 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -89,7 +88,6 @@ exports[`Renderer:Page classNames 1`] = `
<div
className="cxd-Page cxd-Page--withSidebar"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-aside cxd-Page-aside--withWidth aside-class-name"
@ -1056,7 +1054,6 @@ exports[`Renderer:Page initApi 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -1090,7 +1087,6 @@ exports[`Renderer:Page initApi error show Message 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -1140,7 +1136,6 @@ exports[`Renderer:Page initApi reFetch when condition changes 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -1174,7 +1169,6 @@ exports[`Renderer:Page initApi reFetch when condition changes 2`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2120,7 +2114,6 @@ exports[`Renderer:Page initApi show loading 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2154,7 +2147,6 @@ exports[`Renderer:Page initApi show loading 2`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2188,7 +2180,6 @@ exports[`Renderer:Page initApi silentPolling 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2222,7 +2213,6 @@ exports[`Renderer:Page initApi silentPolling 2`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2256,7 +2246,6 @@ exports[`Renderer:Page initApi silentPolling 3`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2284,7 +2273,6 @@ exports[`Renderer:Page initApi silentPolling 4`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2312,7 +2300,6 @@ exports[`Renderer:Page initData 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2340,7 +2327,6 @@ exports[`Renderer:Page initFetchOn trigger initApi fetch when condition becomes
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2374,7 +2360,6 @@ exports[`Renderer:Page location query 1`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"
@ -2402,7 +2387,6 @@ exports[`Renderer:Page location query 2`] = `
<div
className="cxd-Page"
onClick={[Function]}
style={Object {}}
>
<div
className="cxd-Page-content"

View File

@ -0,0 +1,41 @@
import '../../src/utils/tpl.ts';
import '../../src/utils/tpl-builtin';
import '../../src/utils/tpl-lodash';
import {buildStyle} from '../../src/utils/style';
test('style var background', () => {
expect(
buildStyle('${style}', {
style: {
backgroundImage: 'http://www.example.com/a.png'
}
})
).toEqual({
backgroundImage: 'url("http://www.example.com/a.png")'
});
expect(
buildStyle(
{
backgroundImage: 'http://www.example.com/a.png'
},
{}
)
).toEqual({
backgroundImage: 'url("http://www.example.com/a.png")'
});
});
test('style case', () => {
expect(
buildStyle(
{
'font-size': '10'
},
{}
)
).toEqual({
fontSize: '10'
});
});

View File

@ -8,6 +8,7 @@ import {BaseSchema, SchemaExpression} from '../Schema';
import {evalExpression} from '../utils/tpl';
import {resolveVariable, resolveVariableAndFilter} from '../utils/tpl-builtin';
import {ClassNamesFn} from '../theme';
import {buildStyle} from '../utils/style';
/**
* Badge
@ -91,6 +92,8 @@ export class Badge extends React.Component<BadgeProps, object> {
const {classnames: cx, badge, data} = this.props;
let {mode = 'dot', level = 'danger', style} = badge as BadgeSchema;
const customStyle = buildStyle(style, data);
if (typeof level === 'string' && level[0] === '$') {
level = resolveVariableAndFilter(level, data);
}
@ -100,7 +103,7 @@ export class Badge extends React.Component<BadgeProps, object> {
return (
<span
className={cx('Badge-dot', `Badge--${position}`, `Badge--${level}`)}
style={{...offsetStyle, ...sizeStyle, ...style}}
style={{...offsetStyle, ...sizeStyle, ...customStyle}}
>
{animationElement}
</span>
@ -113,7 +116,7 @@ export class Badge extends React.Component<BadgeProps, object> {
`Badge--${position}`,
`Badge--${level}`
)}
style={{...offsetStyle, ...sizeStyle, ...style}}
style={{...offsetStyle, ...sizeStyle, ...customStyle}}
>
{text}
{animationElement}
@ -132,7 +135,7 @@ export class Badge extends React.Component<BadgeProps, object> {
`Badge-ribbon--${position}`,
`Badge--${level}`
)}
style={{...sizeStyle, ...style}}
style={{...sizeStyle, ...customStyle}}
>
{text}
{animationElement}

View File

@ -1,6 +1,7 @@
import React from 'react';
import {isClickOnInput} from '../utils/helper';
import {ClassNamesFn, themeable, ThemeProps} from '../theme';
import {buildStyle} from '../utils/style';
export interface CardProps extends ThemeProps {
className?: string;
headerClassName?: string;
@ -29,6 +30,7 @@ export interface CardProps extends ThemeProps {
secondary?: string | JSX.Element;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
classnames: ClassNamesFn;
data?: any;
}
export class Card extends React.Component<CardProps> {
@ -88,7 +90,8 @@ export class Card extends React.Component<CardProps> {
descriptionPlaceholder,
secondary,
avatar,
avatarText
avatarText,
data
} = this.props;
let heading = null;
@ -111,7 +114,7 @@ export class Card extends React.Component<CardProps> {
) : avatarText ? (
<span
className={cx('Card-avtarText', avatarTextClassName)}
style={avatarTextStyle}
style={buildStyle(avatarTextStyle, data)}
>
{avatarText}
</span>

View File

@ -2,6 +2,7 @@ import React from 'react';
import {Renderer, RendererProps} from '../factory';
import {BaseSchema, SchemaClassName, SchemaCollection} from '../Schema';
import {SchemaNode} from '../types';
import {buildStyle} from '../utils/style';
/**
* Container
@ -80,14 +81,18 @@ export default class Container<T> extends React.Component<
wrapperComponent,
size,
classnames: cx,
style
style,
data
} = this.props;
const Component =
(wrapperComponent as keyof JSX.IntrinsicElements) || 'div';
return (
<Component className={cx('Container', className)} style={style}>
<Component
className={cx('Container', className)}
style={buildStyle(style, data)}
>
{this.renderBody()}
</Component>
);

View File

@ -31,6 +31,7 @@ import {SchemaRemark} from './Remark';
import {onAction} from 'mobx-state-tree';
import mapValues from 'lodash/mapValues';
import {resolveVariable} from '../utils/tpl-builtin';
import {buildStyle} from '../utils/style';
/**
*
@ -722,10 +723,7 @@ export default class Page extends React.Component<PageProps> {
? ~regions.indexOf('aside')
: aside && (!Array.isArray(aside) || aside.length);
let styleVar =
typeof style === 'string'
? resolveVariable(style, data) || {}
: mapValues(style, s => resolveVariable(s, data) || s);
const styleVar = buildStyle(style, data);
return (
<div

View File

@ -7,6 +7,7 @@ import {Renderer, RendererProps} from '../factory';
import {BaseSchema, SchemaExpression, SchemaObject, SchemaTpl} from '../Schema';
import {resolveVariableAndFilter} from '../utils/tpl-builtin';
import {visibilityFilter} from '../utils/helper';
import {buildStyle} from '../utils/style';
export type PropertyItemProps = {
/**
@ -167,7 +168,8 @@ export default class Property extends React.Component<PropertyProps, object> {
contentStyle,
labelStyle,
separator = ': ',
mode = 'table'
mode = 'table',
data
} = this.props;
return rows.map((row, key) => {
return (
@ -175,10 +177,12 @@ export default class Property extends React.Component<PropertyProps, object> {
{row.map((property, index) => {
return mode === 'table' ? (
<React.Fragment key={`item-${index}`}>
<th style={labelStyle}>{render('label', property.label)}</th>
<th style={buildStyle(labelStyle, data)}>
{render('label', property.label)}
</th>
<td
colSpan={property.span + property.span - 1} // 需要再补上 th 所占的列数
style={contentStyle}
style={buildStyle(contentStyle, data)}
>
{render('content', property.content)}
</td>
@ -186,10 +190,10 @@ export default class Property extends React.Component<PropertyProps, object> {
) : (
<td
colSpan={property.span}
style={contentStyle}
style={buildStyle(contentStyle, data)}
key={`item-${index}`}
>
<span style={labelStyle}>
<span style={buildStyle(labelStyle, data)}>
{render('label', property.label)}
</span>
{separator}
@ -210,6 +214,7 @@ export default class Property extends React.Component<PropertyProps, object> {
classnames: cx,
className,
titleStyle,
data,
mode = 'table'
} = this.props;
@ -218,7 +223,7 @@ export default class Property extends React.Component<PropertyProps, object> {
return (
<div
className={cx('Property', `Property--${mode}`, className)}
style={style}
style={buildStyle(style, data)}
>
<table>
{title ? (
@ -226,7 +231,7 @@ export default class Property extends React.Component<PropertyProps, object> {
<tr>
<th
colSpan={mode === 'table' ? column + column : column}
style={titleStyle}
style={buildStyle(titleStyle, data)}
>
{title}
</th>

View File

@ -6,6 +6,7 @@ import {anyChanged, getPropValue} from '../utils/helper';
import {escapeHtml} from '../utils/tpl-builtin';
import {BaseSchema, SchemaTpl} from '../Schema';
import {BadgeSchema, withBadge} from '../components/Badge';
import {buildStyle} from '../utils/style';
/**
* tpl
@ -115,7 +116,8 @@ export class Tpl extends React.Component<TplProps, object> {
wrapperComponent,
inline,
classnames: cx,
style
style,
data
} = this.props;
const Component = wrapperComponent || (inline ? 'span' : 'div');
@ -123,7 +125,7 @@ export class Tpl extends React.Component<TplProps, object> {
<Component
ref={this.htmlRef}
className={cx('TplField', className)}
style={style}
style={buildStyle(style, data)}
>
<span>{this.getContent()}</span>
</Component>

View File

@ -4,6 +4,7 @@ import {BaseSchema, SchemaCollection} from '../Schema';
import {resolveVariable} from '../utils/tpl-builtin';
import {SchemaNode} from '../types';
import mapValues from 'lodash/mapValues';
import {buildStyle} from '../utils/style';
/**
* Wrapper
@ -65,11 +66,6 @@ export default class Wrapper extends React.Component<WrapperProps, object> {
return this.renderBody();
}
let styleVar =
typeof style === 'string'
? resolveVariable(style, data) || {}
: mapValues(style, s => resolveVariable(s, data) || s);
return (
<div
className={cx(
@ -77,7 +73,7 @@ export default class Wrapper extends React.Component<WrapperProps, object> {
size && size !== 'none' ? `Wrapper--${size}` : '',
className
)}
style={styleVar}
style={buildStyle(style, data)}
>
{this.renderBody()}
</div>

56
src/utils/style.ts Normal file
View File

@ -0,0 +1,56 @@
/**
* helper
*/
import {resolveVariableAndFilter} from './tpl-builtin';
import mapValues from 'lodash/mapValues';
import camelCase from 'lodash/camelCase';
function autoAddImageURL(image: string) {
// 只支持单个的情况,并简单滤掉 linear-gradient 等情况
if (
typeof image === 'string' &&
image.indexOf(',') === -1 &&
image.indexOf('(') === -1
) {
return `url("${image}")`;
}
return image;
}
/**
* style
* 1.
* 2. font-size fontSize
* 3. image url
*/
export function buildStyle(style: any, data: any) {
if (!style) {
return style;
}
let styleVar =
typeof style === 'string'
? resolveVariableAndFilter(style, data, '| raw') || {}
: mapValues(style, s => resolveVariableAndFilter(s, data, '| raw') || s);
Object.keys(styleVar).forEach((key: string) => {
if (key.indexOf('-') !== -1) {
styleVar[camelCase(key)] = styleVar[key];
delete styleVar[key];
}
});
if (styleVar.backgroundImage) {
styleVar.backgroundImage = autoAddImageURL(styleVar.backgroundImage);
}
if (styleVar.borderImage) {
styleVar.borderImage = autoAddImageURL(styleVar.borderImage);
}
if (styleVar.listStyleImage) {
styleVar.listStyleImage = autoAddImageURL(styleVar.listStyleImage);
}
return styleVar;
}