Skip to content

Commit

Permalink
✨ feat: Add share shield
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Sep 28, 2023
1 parent 0c9f706 commit 2deb3ad
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/ShieldShare/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
nav: components
group: shields
title: Share
order: 7
---

<code src="./index.tsx" inline></code>
55 changes: 55 additions & 0 deletions src/ShieldShare/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useControls, useCreateStore } from '@lobehub/ui';
import { folder } from 'leva';
import { pick } from 'lodash-es';
import { memo, useMemo } from 'react';

import MarkdownStorybook from '@/components/MarkdownStorybook';
import { shareShieldControlsPickList } from '@/const/shareShieldControls';
import { shieldBaseControls } from '@/const/shieldBaseControls';
import { genShareShields } from '@/services/genShareShield';

const controls = {
/* eslint-disable sort-keys-fix/sort-keys-fix */
title: {
value: 'Check this GitHub repository out 🤯 LobeChat',
rows: 4,
},
desc: {
value:
'An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application.',
rows: 8,
},
hashtags: 'chatbot, chatGPT, openAI',
url: 'https://github.com/lobehub/lobe-chat',
['⚒️']: folder(
{
...pick(shieldBaseControls, ['style', 'color']),
labelColor: {
...shieldBaseControls.labelColor,
value: 'black',
},
logoColor: {
...shieldBaseControls.logoColor,
value: 'white',
},
},
{
collapsed: true,
},
),
/* eslint-enable */
};
const pickControls = { ['✅']: folder(shareShieldControlsPickList, { collapsed: true }) };

const Share = memo(() => {
const store = useCreateStore();

const options = useControls(controls, { store });
const pickOptions = useControls(pickControls, { store });

const md = useMemo(() => genShareShields(options, pickOptions), [options, pickOptions]);

return <MarkdownStorybook levaStore={store}>{md.join('\n\n')}</MarkdownStorybook>;
});

export default Share;
143 changes: 143 additions & 0 deletions src/const/shareShieldControls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { identity, pickBy } from 'lodash-es';
import qs from 'query-string';

import { colorOptions } from '@/const/shieldBaseControls';
import { ShieldsBaseOptions } from '@/types/shields';
import { genPickList } from '@/utils/genPickList';

export interface shareShieldControlsItem extends Partial<ShieldsBaseOptions> {
genLink?: (props: {
desc?: string;
hashtags?: string;
title?: string;
url?: string;
}) => string | undefined;
}

const formateHashtags = (hashtags: string): string[] =>
hashtags.replaceAll(',', ',').replaceAll(' ', '').split(',');

const stringifyHashtags = (hashtags: string, joinfix: string = ',', prefix?: string) => {
let tags = formateHashtags(hashtags.trim());
if (prefix) tags = tags.map((tag) => prefix + tag);
return tags.filter(Boolean).join(joinfix);
};

export const shareShieldControls: {
[key: string]: shareShieldControlsItem;
} = {
/* eslint-disable sort-keys-fix/sort-keys-fix */
twitter: {
logo: 'twitter',
logoColor: 'white',
color: colorOptions.geekblue,
genLink: ({ url, title, desc, hashtags }) => {
const query = pickBy(
{
text: [title, desc].filter(Boolean).join(' - '),
url,
hashtags: hashtags && stringifyHashtags(hashtags),
},
identity,
) as any;
return qs.stringifyUrl({
url: 'https://twitter.com/intent/tweet',
query,
});
},
},
telegram: {
logo: 'telegram',
logoColor: 'white',
color: colorOptions.geekblue,
genLink: ({ url, title, desc, hashtags }) => {
const query = pickBy(
{
text: [
[title, desc].filter(Boolean).join(' - '),
hashtags && stringifyHashtags(hashtags, ' ', '#'),
]
.filter(Boolean)
.join(' '),
url,
},
identity,
) as any;
return qs.stringifyUrl({
url: 'https://t.me/share/url"',
query,
});
},
},
whatsapp: {
logo: 'whatsapp',
logoColor: 'white',
color: colorOptions.geekblue,
genLink: ({ url, title, desc, hashtags }) => {
const query = pickBy(
{
text: [
[title, desc].filter(Boolean).join(' - '),
url,
hashtags && stringifyHashtags(hashtags, ' ', '#'),
]
.filter(Boolean)
.join(' '),
},
identity,
) as any;
return qs.stringifyUrl({
url: 'https://api.whatsapp.com/send"',
query,
});
},
},
weibo: {
logo: 'sinaweibo',
logoColor: 'white',
color: colorOptions.geekblue,
genLink: ({ url, title, desc, hashtags }) => {
const query = pickBy(
{
sharesource: 'weibo',
title: [
[title, desc].filter(Boolean).join(' - '),
hashtags && stringifyHashtags(hashtags, ' ', '#'),
]
.filter(Boolean)
.join(' '),
url,
},
identity,
) as any;
return qs.stringifyUrl({
url: 'http://service.weibo.com/share/share.php',
query,
});
},
},
qq: {
logo: 'tencentqq',
logoColor: 'white',
color: colorOptions.geekblue,
genLink: ({ url, title, desc, hashtags }) => {
const query = pickBy(
{
title,
desc: [desc, hashtags && stringifyHashtags(hashtags, ' ', '#')].filter(Boolean).join(' '),
summary: [title, desc].filter(Boolean).join(' - '),
url,
sharesource: 'qzone',
},
identity,
) as any;
return qs.stringifyUrl({
url: 'http://connect.qq.com/widget/shareqq/index.html',
query,
});
},
},
/* eslint-enable */
};

export const shareShieldControlsPickList = genPickList(shareShieldControls);
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { default as ReadmeFeatures } from './ReadmeFeatures';
export { default as ReadmeHero } from './ReadmeHero';
export { default as ReadmeInstallation } from './ReadmeInstallation';
export { default as ReadmeLicense } from './ReadmeLicense';
export { default as ShieldsBilibili } from './ShieldsBilibili';
export * from './ShieldsCustom';
export { default as ShieldsDiscord } from './ShieldsDiscord';
export * from './ShieldsGithub';
Expand Down
54 changes: 54 additions & 0 deletions src/services/genShareShield.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { identity, pickBy } from 'lodash-es';
import qs from 'query-string';
import urlJoin from 'url-join';

import { shareShieldControls, shareShieldControlsItem } from '@/const/shareShieldControls';
import { SHIELD_BADGE_URL } from '@/const/url';
import { ShieldsBaseOptions } from '@/types/shields';
import { formatCustomLabel } from '@/utils/formatCustomLabel';
import { genShield } from '@/utils/genShield';

type ShareShieldOptions = ShieldsBaseOptions &
shareShieldControlsItem & {
desc?: string;
hashtags?: string;
name: string;
title?: string;
url?: string;
};

export const genSharehield = (options: ShareShieldOptions) => {
console.log(options);

const { name, genLink, title, desc, hashtags, url, color, label, ...config } = options;

const defShield = qs.stringifyUrl({
query: pickBy(config, identity) as any,
url: urlJoin(
SHIELD_BADGE_URL,
formatCustomLabel({
color: (color as string) || 'black',
label: `share on ${label}`,
}),
),
});
const defLink = genLink?.({ desc, hashtags, title, url });

return genShield(`share-${name}`, defShield, defLink);
};

export const genShareShields = (
options: Partial<ShareShieldOptions> | any,
pickOptions: { [key: string]: boolean },
) => {
const defShields: string[] = [];
const defLinks: string[] = [];

for (const [name, config] of Object.entries(shareShieldControls)) {
if (!pickOptions[name]) continue;
const data = genSharehield({ name, ...config, ...options, label: name });
defShields.push(data[0]);
defLinks.push(data[1]);
}
return [defShields.join('\n'), defLinks.join('\n')];
};

0 comments on commit 2deb3ad

Please sign in to comment.