Skip to content

Commit

Permalink
Merge pull request #641 from linbudu599/feat/useFavicon
Browse files Browse the repository at this point in the history
Feat/use favicon
  • Loading branch information
awmleer authored Sep 10, 2020
2 parents e853fa5 + 0f46a93 commit e284e70
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
},
"devDependencies": {
"@alifd/next": "^1.20.6",
"@types/enzyme": "^3.10.5",
"antd": "^3.26.6",
"enzyme-adapter-react-16": "^1.15.4",
"react-drag-listview": "^0.1.6",
"umi-request": "^1.0.8"
},
Expand Down
2 changes: 2 additions & 0 deletions packages/hooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import useWhyDidYouUpdate from './useWhyDidYouUpdate';
import useTitle from './useTitle';
import useNetwork from './useNetwork';
import useTimeout from './useTimeout';
import useFavicon from './useFavicon';
import useCountDown from './useCountDown';

const useControlledValue: typeof useControllableValue = function (...args) {
Expand Down Expand Up @@ -114,5 +115,6 @@ export {
useTitle,
useNetwork,
useTimeout,
useFavicon,
useCountDown,
};
58 changes: 58 additions & 0 deletions packages/hooks/src/useFavicon/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useState } from 'react';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import useFavicon from '../index';

Enzyme.configure({ adapter: new Adapter() });

// 直接导入demo1.tsx作为测试会报错(import { useFavicon } from 'ahooks')
const DEFAULT_FAVICON_URL = 'https://ahooks.js.org/simple-logo.svg';
const GOOGLE_FAVICON_URL = 'https://www.google.com/favicon.ico';

const App: React.FC = () => {
const [url, setUrl] = useState<string>(DEFAULT_FAVICON_URL);
useFavicon(url);
return (
<>
<p>
当前Favicon: <span>{url}</span>
</p>
<button
id="google"
style={{ marginRight: 16 }}
onClick={() => {
setUrl(GOOGLE_FAVICON_URL);
}}
>
Change To Google Favicon
</button>
<button
id="ahooks"
onClick={() => {
setUrl(DEFAULT_FAVICON_URL);
}}
>
Back To AHooks Favicon
</button>
</>
);
};

describe.only('useFavicon Hook', () => {
it('should be defined as function', () => {
expect(useFavicon).toBeDefined();
expect(typeof useFavicon).toBe('function');
});

it('should toggle favicon when URL changed', () => {
const wrapper = mount(<App />);
const currentFaviconURL = wrapper.find('span').at(0);
const toggleToGoogleBtn = wrapper.find('button').at(0);
const toggleToAHooksBtn = wrapper.find('button').at(1);
expect(currentFaviconURL.text()).toBe(DEFAULT_FAVICON_URL);
toggleToGoogleBtn.simulate('click');
expect(currentFaviconURL.text()).toBe(GOOGLE_FAVICON_URL);
toggleToAHooksBtn.simulate('click');
expect(currentFaviconURL.text()).toBe(DEFAULT_FAVICON_URL);
});
});
45 changes: 45 additions & 0 deletions packages/hooks/src/useFavicon/demo/demo1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* title: Basic usage
* desc: Page favicon setup and toggle
*
* title.zh-CN: 基本用法
* desc.zh-CN: 页面标识 favicon 设置 与 切换
*/

import React, { useState } from 'react';
import { useFavicon } from 'ahooks';

export const DEFAULT_FAVICON_URL = 'https://ahooks.js.org/simple-logo.svg';

export const GOOGLE_FAVICON_URL = 'https://www.google.com/favicon.ico';

export default () => {
const [url, setUrl] = useState<string>(DEFAULT_FAVICON_URL);

useFavicon(url);

return (
<>
<p>
Current Favicon: <span>{url}</span>
</p>
<button
id="google"
style={{ marginRight: 16 }}
onClick={() => {
setUrl(GOOGLE_FAVICON_URL);
}}
>
Change To Google Favicon
</button>
<button
id="ahooks"
onClick={() => {
setUrl(DEFAULT_FAVICON_URL);
}}
>
Back To AHooks Favicon
</button>
</>
);
};
32 changes: 32 additions & 0 deletions packages/hooks/src/useFavicon/index.en-US.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: useFavicon
nav:
title: Hooks
path: /hooks
group:
title: Dom
path: /dom
---

# useFavicon

Set or configure page favicon URL.

## Example

### Basic Usage

<code src="./demo/demo1.tsx" />


## API

```javascript
useFavicon(faviconURL: string)
```

### Params

| Params | Description | Type | Default |
| ---------- | -------------------------------------------- | ------ | ------- |
| faviconURL | favicon URL, support `svg`/`png`/`ico`/`gif` | string | none |
34 changes: 34 additions & 0 deletions packages/hooks/src/useFavicon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect } from 'react';

// image/vnd.microsoft.icon MIME类型只有当图像真的是ICO文件时才会起作用
// image/x-icon 会同时也适用于位图与GIF
// 主要是为了兼容扩展名为ico的非ico文件
const ImgTypeMap = {
SVG: 'image/svg+xml',
ICO: 'image/x-icon',
GIF: 'image/gif',
PNG: 'image/png',
};

type ImgTypes = keyof typeof ImgTypeMap;

const useFavicon = (favUrl: string): void => {
const cutUrl = favUrl.split('.');
const imgSuffix = cutUrl[cutUrl.length - 1].toLocaleUpperCase() as ImgTypes;

useEffect(() => {
if (!favUrl) return;

const link: HTMLLinkElement =
document.querySelector("link[rel*='icon']") || document.createElement('link');

link.type = ImgTypeMap[imgSuffix];
link.href = favUrl;
// 大部分浏览器只会识别'icon' 只有IE会识别整个名称'shortcut icon'
link.rel = 'shortcut icon';

document.getElementsByTagName('head')[0].appendChild(link);
}, [favUrl]);
};

export default useFavicon;
32 changes: 32 additions & 0 deletions packages/hooks/src/useFavicon/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: useFavicon
nav:
title: Hooks
path: /hooks
group:
title: Dom
path: /dom
---

# useFavicon

用于 设置 与 切换 页面 favicon。

## 代码演示

### 基础用法

<code src="./demo/demo1.tsx" />


## API

```javascript
useFavicon(faviconURL: string)
```

### Params

| 参数 | 说明 | 类型 | 默认值 |
| ---------- | -------------------------------------------------- | ------ | ------ |
| faviconURL | favicon地址, 支持`svg`/`png`/`ico`/`gif`后缀的图片 | string ||

0 comments on commit e284e70

Please sign in to comment.