Skip to content

Commit

Permalink
feat: clickable entry id in ai daily
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Aug 7, 2024
1 parent acfb35a commit 0ffe1e5
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 8 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
"rehype-parse": "9.0.0",
"rehype-sanitize": "6.0.0",
"rehype-stringify": "10.0.0",
"remark-parse": "11.0.0",
"remark-rehype": "11.1.0",
"semver": "7.6.3",
"shiki": "1.12.0",
"sonner": "^1.5.0",
Expand Down
29 changes: 29 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useNavigateEntry } from "@renderer/hooks/biz/useNavigateEntry"
import { FeedViewType } from "@renderer/lib/enum"
import { useEntryContentContext } from "@renderer/modules/entry-content/hooks"
import { useEntry } from "@renderer/store/entry"
import { useCallback } from "react"

import type { LinkProps } from "../../link"
import {
Expand All @@ -13,6 +16,19 @@ import { ensureAndRenderTimeStamp } from "../utils"
export const MarkdownLink = (props: LinkProps) => {
const { view } = useEntryContentContext()

const entryId = (/^\w{17}$/.test(props.href)) ? props.href : null
const entry = useEntry(entryId)

const navigate = useNavigateEntry()
const onClick = useCallback((e: React.MouseEvent) => {
if (entryId) {
e.preventDefault()
navigate({
entryId,
})
}
}, [entryId, navigate])

const parseTimeStamp = view === FeedViewType.Audios
if (parseTimeStamp) {
const childrenText = props.children
Expand All @@ -22,6 +38,7 @@ export const MarkdownLink = (props: LinkProps) => {
if (renderer) return renderer
}
}

return (
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
Expand All @@ -30,6 +47,7 @@ export const MarkdownLink = (props: LinkProps) => {
href={props.href}
title={props.title}
target="_blank"
onClick={onClick}
>
{props.children}

Expand All @@ -41,7 +59,7 @@ export const MarkdownLink = (props: LinkProps) => {
{!!props.href && (
<TooltipPortal>
<TooltipContent align="start" className="break-all" side="bottom">
{props.href}
{entry?.entries.title || props.href}
</TooltipContent>
</TooltipPortal>
)}
Expand Down
42 changes: 42 additions & 0 deletions src/renderer/src/lib/parse-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
MarkdownLink,
} from "@renderer/components/ui/markdown/renderers"
import { toJsxRuntime } from "hast-util-to-jsx-runtime"
import { createElement } from "react"
import { Fragment, jsx, jsxs } from "react/jsx-runtime"
import rehypeSanitize from "rehype-sanitize"
import rehypeStringify from "rehype-stringify"
import remarkParse from "remark-parse"
import remarkRehype from "remark-rehype"
import { unified } from "unified"
import { VFile } from "vfile"

export const parseMarkdown = async (
content: string,
) => {
const file = new VFile(content)

const pipeline = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeSanitize)
.use(rehypeStringify)

const tree = pipeline.parse(content)

const hastTree = pipeline.runSync(tree, file)

return {
content: toJsxRuntime(hastTree, {
Fragment,
ignoreInvalidStyle: true,
jsx: (type, props, key) => jsx(type as any, props, key),
jsxs: (type, props, key) => jsxs(type as any, props, key),
passNode: true,
components: {
a: ({ node, ...props }) =>
createElement(MarkdownLink, { ...props } as any),
},
}),
}
}
23 changes: 16 additions & 7 deletions src/renderer/src/modules/entry-content/daily.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Card, CardHeader } from "@renderer/components/ui/card"
import { Collapse, CollapseGroup } from "@renderer/components/ui/collapse"
import { LoadingCircle } from "@renderer/components/ui/loading"
import { Markdown } from "@renderer/components/ui/markdown"
import { ScrollArea } from "@renderer/components/ui/scroll-area"
import {
Tooltip,
Expand All @@ -12,10 +11,11 @@ import { useAuthQuery } from "@renderer/hooks/common"
import { apiClient } from "@renderer/lib/api-fetch"
import { defineQuery } from "@renderer/lib/defineQuery"
import type { FeedViewType } from "@renderer/lib/enum"
import { parseMarkdown } from "@renderer/lib/parse-markdown"
import { cn } from "@renderer/lib/utils"
import { MarkAllButton } from "@renderer/modules/entry-column/mark-all-button"
import type { FC } from "react"
import { useState } from "react"
import { useEffect, useState } from "react"

type DailyView = Extract<
FeedViewType,
Expand Down Expand Up @@ -153,6 +153,15 @@ const DailyReportContent: FC<{
const [markAllButtonRef, setMarkAllButtonRef] =
useState<HTMLButtonElement | null>(null)

const [eleContent, setEleContent] = useState<JSX.Element>()
useEffect(() => {
if (content.data) {
parseMarkdown(content.data).then(({ content }) => {
setEleContent(content)
})
}
}, [content.data])

return (
<Card className="border-none bg-transparent">
<CardHeader className="space-y-0 p-0">
Expand All @@ -164,14 +173,14 @@ const DailyReportContent: FC<{
{content.isLoading ? (
<LoadingCircle size="large" className="mt-8 text-center" />
) : (
content.data && (
<Markdown className="prose-sm mt-4 px-6 prose-p:my-1 prose-ul:my-1">
{content.data}
</Markdown>
eleContent && (
<div className="prose-sm mt-4 px-6 prose-p:my-1 prose-ul:my-1">
{eleContent}
</div>
)
)}
</ScrollArea.ScrollArea>
{content.data && (
{eleContent && (
<button
type="button"
onClick={() => {
Expand Down

0 comments on commit 0ffe1e5

Please sign in to comment.