feat: feed add markdown support
This commit is contained in:
parent
4d15cccd1b
commit
56bbe09005
@ -311,6 +311,9 @@ importers:
|
||||
react-router-dom:
|
||||
specifier: ^6.15.0
|
||||
version: 6.15.0(react-dom@18.2.0)(react@18.2.0)
|
||||
rehype-external-links:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
socket.io-client:
|
||||
specifier: ^4.7.2
|
||||
version: 4.7.2
|
||||
@ -5013,7 +5016,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@ -5023,7 +5025,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@ -5033,7 +5034,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@ -5043,7 +5043,6 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@ -13642,6 +13641,12 @@ packages:
|
||||
vfile-location: 5.0.2
|
||||
web-namespaces: 2.0.1
|
||||
|
||||
/hast-util-is-element@3.0.0:
|
||||
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
dev: false
|
||||
|
||||
/hast-util-parse-selector@3.1.1:
|
||||
resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==}
|
||||
dependencies:
|
||||
@ -14330,6 +14335,11 @@ packages:
|
||||
resolution: {integrity: sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==}
|
||||
dev: false
|
||||
|
||||
/is-absolute-url@4.0.1:
|
||||
resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: false
|
||||
|
||||
/is-absolute@1.0.0:
|
||||
resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -21072,6 +21082,17 @@ packages:
|
||||
resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==}
|
||||
dev: false
|
||||
|
||||
/rehype-external-links@3.0.0:
|
||||
resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==}
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@ungap/structured-clone': 1.2.0
|
||||
hast-util-is-element: 3.0.0
|
||||
is-absolute-url: 4.0.1
|
||||
space-separated-tokens: 2.0.2
|
||||
unist-util-visit: 5.0.0
|
||||
dev: false
|
||||
|
||||
/rehype-raw@6.1.1:
|
||||
resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==}
|
||||
dependencies:
|
||||
|
@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Editor, EditorProps } from '@bytemd/react';
|
||||
import { plugins } from './plugins';
|
||||
import 'bytemd/dist/index.css';
|
||||
import './style.less';
|
||||
import { useLocale } from './useLocale';
|
||||
|
||||
interface MarkdownEditorProps extends EditorProps {}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import loadable from '@loadable/component';
|
||||
import 'bytemd/dist/index.css';
|
||||
import './style.less';
|
||||
|
||||
export const MarkdownEditor = loadable(() =>
|
||||
import('./editor').then((module) => module.MarkdownEditor)
|
||||
|
@ -1,6 +1,13 @@
|
||||
import gfm from '@bytemd/plugin-gfm';
|
||||
import { BytemdPlugin } from 'bytemd';
|
||||
import externalLinks from 'rehype-external-links';
|
||||
|
||||
export const plugins = [
|
||||
export const plugins: BytemdPlugin[] = [
|
||||
gfm(),
|
||||
// Add more plugins here
|
||||
{
|
||||
rehype: (p) =>
|
||||
p.use(externalLinks, {
|
||||
target: '_blank',
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
@ -7,12 +7,20 @@
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.markdown {
|
||||
.markdown-body {
|
||||
a {
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.bytemd {
|
||||
@apply bg-zinc-900 border-zinc-800 text-foreground;
|
||||
@apply text-foreground border-zinc-800 bg-zinc-900;
|
||||
|
||||
.bytemd-toolbar {
|
||||
@apply bg-zinc-900 border-zinc-800;
|
||||
@apply border-zinc-800 bg-zinc-900;
|
||||
|
||||
.bytemd-toolbar-icon:hover {
|
||||
@apply bg-muted;
|
||||
@ -24,7 +32,7 @@
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
@apply bg-zinc-900 text-foreground;
|
||||
@apply text-foreground bg-zinc-900;
|
||||
|
||||
.CodeMirror-cursor {
|
||||
@apply border-foreground;
|
||||
|
@ -1,15 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Viewer } from '@bytemd/react';
|
||||
import { plugins } from './plugins';
|
||||
import 'bytemd/dist/index.css';
|
||||
import './style.less';
|
||||
|
||||
interface MarkdownViewerProps {
|
||||
value: string;
|
||||
}
|
||||
export const MarkdownViewer: React.FC<MarkdownViewerProps> = React.memo(
|
||||
(props) => {
|
||||
return <Viewer plugins={plugins} value={props.value ?? ''} />;
|
||||
return (
|
||||
<div className="markdown">
|
||||
<Viewer plugins={plugins} value={props.value ?? ''} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
MarkdownViewer.displayName = 'MarkdownViewer';
|
||||
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||
import { Badge } from '../ui/badge';
|
||||
import dayjs from 'dayjs';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
||||
import { MarkdownViewer } from '../MarkdownEditor';
|
||||
|
||||
type FeedEventItemType = AppRouterOutput['feed']['events'][number];
|
||||
|
||||
@ -12,7 +13,9 @@ export const FeedEventItem: React.FC<{ event: FeedEventItemType }> = React.memo(
|
||||
<div className="border-muted flex items-center rounded-lg border px-4 py-2">
|
||||
<div className="flex-1 gap-2">
|
||||
<div className="mb-2 flex gap-2">
|
||||
<div>{event.eventContent}</div>
|
||||
<div>
|
||||
<MarkdownViewer value={event.eventContent} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
|
@ -87,6 +87,7 @@
|
||||
"react-resizable-panels": "^2.0.12",
|
||||
"react-router": "^6.15.0",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"sonner": "^1.4.3",
|
||||
"str2int": "^1.1.0",
|
||||
@ -99,10 +100,10 @@
|
||||
"devDependencies": {
|
||||
"@i18next-toolkit/cli": "^1.2.2",
|
||||
"@tanstack/router-vite-plugin": "^1.20.5",
|
||||
"@types/jsonexport": "^3.0.5",
|
||||
"@types/leaflet": "^1.9.8",
|
||||
"@types/loadable__component": "^5.13.8",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/jsonexport": "^3.0.5",
|
||||
"@types/react": "^18.2.22",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/react-grid-layout": "^1.3.5",
|
||||
|
@ -43,9 +43,11 @@ export const feedIntegrationRouter = router({
|
||||
}
|
||||
|
||||
if (eventType === 'push') {
|
||||
const pusher = `${_.get(data, 'pusher.name')}<${_.get(data, 'pusher.email')}>`;
|
||||
const pusherName = _.get(data, 'pusher.name');
|
||||
const pusherEmail = _.get(data, 'pusher.email');
|
||||
const commits = _.map(_.get(data, 'commits') as any[], 'id').join(', ');
|
||||
const fullName = _.get(data, 'repository.full_name');
|
||||
const repoUrl = _.get(data, 'repository.html_url');
|
||||
const ref = String(_.get(data, 'ref'));
|
||||
const senderId = String(_.get(data, 'sender.id'));
|
||||
const senderName = String(_.get(data, 'sender.login'));
|
||||
@ -54,7 +56,7 @@ export const feedIntegrationRouter = router({
|
||||
data: {
|
||||
channelId: channelId,
|
||||
eventName: eventType,
|
||||
eventContent: `${pusher} push commit ${commits} to [${ref}] in ${fullName}`,
|
||||
eventContent: `[${pusherName}](${pusherEmail}) push commit **${commits}** to [${ref}] in [${fullName}](${repoUrl})`,
|
||||
tags: [],
|
||||
source: 'github',
|
||||
senderId,
|
||||
@ -69,10 +71,13 @@ export const feedIntegrationRouter = router({
|
||||
serializeJSON(event)
|
||||
);
|
||||
|
||||
console.log('serializeJSON(event)', serializeJSON(event));
|
||||
|
||||
return 'ok';
|
||||
} else if (eventType === 'star') {
|
||||
const starCount = _.get(data, 'repository.stargazers_count');
|
||||
const fullName = _.get(data, 'repository.full_name');
|
||||
const repoUrl = _.get(data, 'repository.html_url');
|
||||
const senderId = String(_.get(data, 'sender.id'));
|
||||
const senderName = String(_.get(data, 'sender.login'));
|
||||
const url = String(_.get(data, 'compare'));
|
||||
@ -80,7 +85,7 @@ export const feedIntegrationRouter = router({
|
||||
data: {
|
||||
channelId: channelId,
|
||||
eventName: eventType,
|
||||
eventContent: `${senderName} star repo [${fullName}], now is ${starCount}.`,
|
||||
eventContent: `${senderName} star repo [${fullName}](${repoUrl}), now is ${starCount}.`,
|
||||
tags: [],
|
||||
source: 'github',
|
||||
senderId,
|
||||
@ -100,6 +105,7 @@ export const feedIntegrationRouter = router({
|
||||
const action = _.get(data, 'action') as 'opened' | 'closed';
|
||||
const starCount = _.get(data, 'repository.stargazers_count');
|
||||
const fullName = _.get(data, 'repository.full_name');
|
||||
const repoUrl = _.get(data, 'repository.html_url');
|
||||
const senderId = String(_.get(data, 'sender.id'));
|
||||
const senderName = String(_.get(data, 'sender.login'));
|
||||
const url = String(_.get(data, 'issue.url'));
|
||||
@ -109,10 +115,10 @@ export const feedIntegrationRouter = router({
|
||||
let eventContent = '';
|
||||
if (action === 'opened') {
|
||||
eventName = 'open_issue';
|
||||
eventContent = `${senderName} open issue [${title}] in repo [${fullName}]`;
|
||||
eventContent = `${senderName} open issue [${title}] in repo [${fullName}](${repoUrl})`;
|
||||
} else if (action === 'closed') {
|
||||
eventName = 'close_issue';
|
||||
eventContent = `${senderName} close issue [${title}] in repo [${fullName}]`;
|
||||
eventContent = `${senderName} close issue [${title}] in repo [${fullName}](${repoUrl})`;
|
||||
}
|
||||
|
||||
if (eventContent) {
|
||||
|
Loading…
Reference in New Issue
Block a user