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

feat(image): allow component to render svg string #692

Merged
merged 2 commits into from
Jan 30, 2022
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
12 changes: 6 additions & 6 deletions components/image/__tests__/__snapshots__/browser.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3042,7 +3042,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down Expand Up @@ -3091,7 +3091,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down Expand Up @@ -3265,7 +3265,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down Expand Up @@ -3314,7 +3314,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down Expand Up @@ -6572,7 +6572,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down Expand Up @@ -6621,7 +6621,7 @@ LoadedCheerio {
width: auto;
height: auto;
object-fit: scale-down;
display: block;
display: inline-block;
}
",
"next": null,
Expand Down
6 changes: 6 additions & 0 deletions components/image/__tests__/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ exports[`Image should render correctly 1`] = `ReactWrapper {}`;
exports[`Image should render correctly 2`] = `ReactWrapper {}`;

exports[`Image should render correctly 3`] = `ReactWrapper {}`;

exports[`Image should render correctly with svg string 1`] = `ReactWrapper {}`;

exports[`Image should render correctly with svg string 2`] = `ReactWrapper {}`;

exports[`Image should render correctly with svg string 3`] = `ReactWrapper {}`;
19 changes: 19 additions & 0 deletions components/image/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const url =
'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO' +
'9TXL0Y4OHwAAAABJRU5ErkJggg=='

const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="15px" height="15px" viewBox="0 0 15 15" fill="none">
<path d="M12.5 8V7.83333C12.5 7.09695 11.903 6.5 11.1667 6.5H10C9.17157 6.5 8.5 7.17157 8.5 8C8.5 8.82843 9.17157 9.5 10 9.5H11C11.8284 9.5 12.5 10.1716 12.5 11C12.5 11.8284 11.8284 12.5 11 12.5H10C9.17157 12.5 8.5 11.8284 8.5 11M8 6.5H3M5.5 6.5V13M0.5 0.5H14.5V14.5H0.5V0.5Z" stroke="black"/></svg>`

describe('Image', () => {
it('should render correctly', async () => {
let wrapper = mount(<Image src={url} />)
Expand All @@ -25,6 +28,22 @@ describe('Image', () => {
expect(() => wrapper.unmount()).not.toThrow()
})

it('should render correctly with svg string', () => {
let wrapper = mount(<Image src={svg} />)
expect(wrapper).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()

wrapper = mount(<Image src={svg} width={20} height={20} />)
wrapper.find('img').at(0).simulate('load')
expect(wrapper).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()

wrapper = mount(<Image src={svg} width={20} height={20} disableSkeleton />)
wrapper.find('img').at(0).simulate('load')
expect(wrapper).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()
})

it('should work correctly with skeleton', async () => {
let wrapper = mount(<Image src={url} width={20} height={20} />)
expect(wrapper.find('.skeleton').length).not.toBe(0)
Expand Down
15 changes: 15 additions & 0 deletions components/image/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const transformDataSource = (src: string) => {
const left = `${src}`.slice(0, 4)
if (encodeURIComponent(left) === '%3Csvg') {
return `data:image/svg+xml;utf8,${src}`
}
return src
}

export const getHostFromUrl = (url: string) => {
try {
return new URL(url).host
} catch (e) {
return url
}
}
9 changes: 1 addition & 8 deletions components/image/image-browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Props as LinkProps } from '../link/link'
import useTheme from '../use-theme'
import ImageBrowserHttpsIcon from './image-browser-https-icon'
import { getBrowserColors, BrowserColors } from './styles'
import { getHostFromUrl } from './helpers'
import useScaleable, { withPureProps, withScaleable } from '../use-scaleable'

export type ImageAnchorProps = Omit<React.AnchorHTMLAttributes<any>, keyof LinkProps>
Expand All @@ -27,14 +28,6 @@ const defaultProps = {
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type ImageBrowserProps = Props & NativeAttrs

const getHostFromUrl = (url: string) => {
try {
return new URL(url).host
} catch (e) {
return url
}
}

const getTitle = (title: string, colors: BrowserColors) => (
<div className="title">
{title}
Expand Down
8 changes: 5 additions & 3 deletions components/image/image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useRef, useState } from 'react'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import useTheme from '../use-theme'
import ImageSkeleton from './image.skeleton'
import { transformDataSource } from './helpers'
import useScaleable, { withPureProps, withScaleable } from '../use-scaleable'

interface Props {
Expand Down Expand Up @@ -35,6 +36,7 @@ const ImageComponent: React.FC<ImageProps> = ({
const [loading, setLoading] = useState<boolean>(true)
const [showSkeleton, setShowSkeleton] = useState<boolean>(true)
const imageRef = useRef<HTMLImageElement>(null)
const url = useMemo(() => transformDataSource(src), [src])

const imageLoaded = () => {
if (!showAnimation) return
Expand Down Expand Up @@ -63,7 +65,7 @@ const ImageComponent: React.FC<ImageProps> = ({
return (
<div className={`image ${className}`}>
{showSkeleton && showAnimation && <ImageSkeleton opacity={loading ? 0.5 : 0} />}
<img ref={imageRef} onLoad={imageLoaded} src={src} {...withPureProps(props)} />
<img ref={imageRef} onLoad={imageLoaded} src={url} {...withPureProps(props)} />
<style jsx>{`
.image {
position: relative;
Expand All @@ -81,7 +83,7 @@ const ImageComponent: React.FC<ImageProps> = ({
width: ${SCALES.width(1, 'auto')};
height: ${SCALES.height(1, 'auto')};
object-fit: scale-down;
display: block;
display: inline-block;
}
`}</style>
</div>
Expand Down
25 changes: 19 additions & 6 deletions pages/en-us/components/image.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Display image content.
title="Basic"
scope={{ Image }}
code={`
<Image width="540px" height="160px" src="/images/custom-domains.png" />
<Image width="280px" height="160px" src="/images/geist-banner.png" />
`}
/>

Expand All @@ -23,8 +23,8 @@ Display image content.
desc="`Image` will show skeleton animation after `width` and `height` props are set."
scope={{ Image }}
code={`
<Image width="540px" height="160px"
src="http://www.deelay.me/2000/https://geist-ui.dev/images/custom-domains.png" />
<Image width="280px" height="160px"
src="http://www.deelay.me/2000/https://geist-ui.dev/images/geist-banner.png" />
`}
/>

Expand All @@ -34,7 +34,7 @@ Display image content.
scope={{ Image, Display, Code }}
code={`
<Image.Browser url="https://geist-ui.dev/en-us/guide/introduction" anchorProps={{ rel: 'nofollow' }}>
<Image width="540px" height="246px" src="https://user-images.githubusercontent.com/11304944/76085431-fd036480-5fec-11ea-8412-9e581425344a.png" />
<Image width="525px" height="300px" src="/images/geist-banner.png" />
</Image.Browser>
`}
/>
Expand All @@ -44,7 +44,7 @@ Display image content.
scope={{ Image, Display, Code }}
code={`
<Image.Browser url="https://geist-ui.dev/en-us/guide/introduction" invert>
<Image width="540px" height="246px" src="https://user-images.githubusercontent.com/11304944/76085431-fd036480-5fec-11ea-8412-9e581425344a.png" />
<Image width="525px" height="300px" src="/images/geist-banner-dark.png" />
</Image.Browser>
`}
/>
Expand All @@ -55,11 +55,24 @@ Display image content.
scope={{ Image, Display, Code }}
code={`
<Display shadow caption={<p>Set the <Code>height</Code> to reduces the possibility of page rerender.</p>}>
<Image width="540px" height="246px" src="/images/branch-domains.png" />
<Image height="246px" src="/images/geist-banner-text.png" />
</Display>
`}
/>

<Playground
title="SVG"
desc="Render svg strings directly"
scope={{ Image }}
code={`
() => {
const svg = \`<svg xmlns="http://www.w3.org/2000/svg" width="15px" height="15px" viewBox="0 0 15 15" fill="none">
<path d="M12.5 8V7.83333C12.5 7.09695 11.903 6.5 11.1667 6.5H10C9.17157 6.5 8.5 7.17157 8.5 8C8.5 8.82843 9.17157 9.5 10 9.5H11C11.8284 9.5 12.5 10.1716 12.5 11C12.5 11.8284 11.8284 12.5 11 12.5H10C9.17157 12.5 8.5 11.8284 8.5 11M8 6.5H3M5.5 6.5V13M0.5 0.5H14.5V14.5H0.5V0.5Z" stroke="black"/></svg>\`
return <Image width="100px" height="50px" src={svg} />
}
`}
/>

<Attributes edit="/pages/en-us/components/image.mdx">
<Attributes.Title>Image.Props</Attributes.Title>

Expand Down
25 changes: 19 additions & 6 deletions pages/zh-cn/components/image.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const meta = {
<Playground
scope={{ Image }}
code={`
<Image width="540px" height="160px" src="/images/custom-domains.png" />
<Image width="280px" height="160px" src="/images/geist-banner.png" />
`}
/>

Expand All @@ -22,8 +22,8 @@ export const meta = {
desc="组件在设置 `width` 与 `height` 属性后会在加载时显示骨架动画。"
scope={{ Image }}
code={`
<Image width="540px" height="160px"
src="http://www.deelay.me/2000/https://geist-ui.dev/images/custom-domains.png" />
<Image width="280px" height="160px"
src="http://www.deelay.me/2000/https://geist-ui.dev/images/geist-banner.png" />
`}
/>

Expand All @@ -33,7 +33,7 @@ export const meta = {
scope={{ Image, Display, Code }}
code={`
<Image.Browser url="https://geist-ui.dev/en-us/guide/introduction" >
<Image width="540px" height="246px" src="https://user-images.githubusercontent.com/11304944/76085431-fd036480-5fec-11ea-8412-9e581425344a.png" />
<Image width="525px" height="300px" src="/images/geist-banner.png" />
</Image.Browser>
`}
/>
Expand All @@ -43,7 +43,7 @@ export const meta = {
scope={{ Image, Display, Code }}
code={`
<Image.Browser url="https://geist-ui.dev/en-us/guide/introduction" invert>
<Image width="540px" height="246px" src="https://user-images.githubusercontent.com/11304944/76085431-fd036480-5fec-11ea-8412-9e581425344a.png" />
<Image width="525px" height="300px" src="/images/geist-banner-dark.png" />
</Image.Browser>
`}
/>
Expand All @@ -54,11 +54,24 @@ export const meta = {
scope={{ Image, Display, Code }}
code={`
<Display shadow caption={<p>设置 <Code>height</Code> 属性可以尽可能的减少重绘。</p>}>
<Image width="540px" height="246px" src="/images/branch-domains.png" />
<Image height="246px" src="/images/geist-banner-text.png" />
</Display>
`}
/>

<Playground
title="SVG"
desc="直接渲染 SVG 字符串"
scope={{ Image }}
code={`
() => {
const svg = \`<svg xmlns="http://www.w3.org/2000/svg" width="15px" height="15px" viewBox="0 0 15 15" fill="none">
<path d="M12.5 8V7.83333C12.5 7.09695 11.903 6.5 11.1667 6.5H10C9.17157 6.5 8.5 7.17157 8.5 8C8.5 8.82843 9.17157 9.5 10 9.5H11C11.8284 9.5 12.5 10.1716 12.5 11C12.5 11.8284 11.8284 12.5 11 12.5H10C9.17157 12.5 8.5 11.8284 8.5 11M8 6.5H3M5.5 6.5V13M0.5 0.5H14.5V14.5H0.5V0.5Z" stroke="black"/></svg>\`
return <Image width="100px" height="50px" src={svg} />
}
`}
/>

<Attributes edit="/pages/zh-cn/components/image.mdx">
<Attributes.Title>Image.Props</Attributes.Title>

Expand Down
Binary file removed public/images/branch-domains.png
Binary file not shown.
Binary file removed public/images/custom-domains.png
Binary file not shown.
Binary file added public/images/geist-banner-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/geist-banner-text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/zeit-react-logo.png
Binary file not shown.