Skip to content

Commit

Permalink
feat(image): allow component to render svg string (#692)
Browse files Browse the repository at this point in the history
* feat(image): allow component to render svg string

* docs(image): update the image content of examples
  • Loading branch information
unix committed Jan 30, 2022
1 parent a32f585 commit 0f126e9
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 29 deletions.
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.

0 comments on commit 0f126e9

Please sign in to comment.