{config.map((section, index) => {
return (
+
{children}
)
diff --git a/src/components/modules/dashboard/comments/CommentAction.tsx b/src/components/modules/dashboard/comments/CommentAction.tsx
index 62bec362ce..8a7e8827aa 100644
--- a/src/components/modules/dashboard/comments/CommentAction.tsx
+++ b/src/components/modules/dashboard/comments/CommentAction.tsx
@@ -8,7 +8,7 @@ import { useModalStack } from '~/components/ui/modal'
import {
useDeleteCommentMutation,
useUpdateCommentStateMutation,
-} from '~/queries/definition/comment'
+} from '~/queries/hooks/comment'
import { DeleteConfirmButton } from '../../shared/DeleteConfirmButton'
import {
diff --git a/src/components/modules/dashboard/comments/CommentBatchActionGroup.tsx b/src/components/modules/dashboard/comments/CommentBatchActionGroup.tsx
index fe10d8b9d5..733067d520 100644
--- a/src/components/modules/dashboard/comments/CommentBatchActionGroup.tsx
+++ b/src/components/modules/dashboard/comments/CommentBatchActionGroup.tsx
@@ -9,7 +9,7 @@ import { toast } from '~/lib/toast'
import {
useDeleteCommentMutation,
useUpdateCommentStateMutation,
-} from '~/queries/definition/comment'
+} from '~/queries/hooks/comment'
import { OffsetHeaderLayout } from '../layouts'
import {
diff --git a/src/components/modules/dashboard/comments/ReplyModal.tsx b/src/components/modules/dashboard/comments/ReplyModal.tsx
index d4680e754e..85b4906efc 100644
--- a/src/components/modules/dashboard/comments/ReplyModal.tsx
+++ b/src/components/modules/dashboard/comments/ReplyModal.tsx
@@ -15,7 +15,7 @@ import { PresentSheet } from '~/components/ui/sheet'
import { useEventCallback } from '~/hooks/common/use-event-callback'
import { useUncontrolledInput } from '~/hooks/common/use-uncontrolled-input'
import { toast } from '~/lib/toast'
-import { useReplyCommentMutation } from '~/queries/definition/comment'
+import { useReplyCommentMutation } from '~/queries/hooks/comment'
import { KAOMOJI_LIST } from './kaomoji'
diff --git a/src/components/modules/note/NoteFooterNavigation.tsx b/src/components/modules/note/NoteFooterNavigation.tsx
index 2b1037a9bb..e6b33f0c88 100644
--- a/src/components/modules/note/NoteFooterNavigation.tsx
+++ b/src/components/modules/note/NoteFooterNavigation.tsx
@@ -40,7 +40,6 @@ export const NoteFooterNavigation = () => {
})}
className="hover:text-accent"
scroll={false}
- prefetch={false}
>
前一篇
@@ -52,7 +51,6 @@ export const NoteFooterNavigation = () => {
href={routeBuilder(Routes.Note, {
id: prevNid.toString(),
})}
- prefetch={false}
scroll={false}
className="hover:text-accent"
>
diff --git a/src/components/modules/post/fab/PostTagsFAB.tsx b/src/components/modules/post/fab/PostTagsFAB.tsx
index 2d3f4255a0..f040b360ee 100644
--- a/src/components/modules/post/fab/PostTagsFAB.tsx
+++ b/src/components/modules/post/fab/PostTagsFAB.tsx
@@ -113,7 +113,6 @@ export const TagDetailModal = (props: { name: string }) => {
onClick={() => {
dismissAll()
}}
- prefetch={false}
href={routeBuilder(Routes.Post, {
category: item.category.slug,
slug: item.slug,
diff --git a/src/components/ui/code-highlighter/shiki/Shiki.tsx b/src/components/ui/code-highlighter/shiki/Shiki.tsx
index 19b9366f9a..360aa7452d 100644
--- a/src/components/ui/code-highlighter/shiki/Shiki.tsx
+++ b/src/components/ui/code-highlighter/shiki/Shiki.tsx
@@ -1,10 +1,9 @@
import { useEffect, useMemo, useState } from 'react'
-import { getHighlighterCore } from 'shiki'
-import getWasm from 'shiki/wasm'
import type { FC } from 'react'
+import { isServerSide } from '~/lib/env'
+
import { ShikiHighLighterWrapper } from './ShikiWrapper'
-import { codeHighlighter } from './utils'
interface Props {
lang: string | undefined
@@ -13,7 +12,15 @@ interface Props {
attrs?: string
}
-const highlighterCore = await (async () => {
+const codeHighlighter = await (async () => {
+ if (isServerSide) return
+ const [{ getHighlighterCore }, getWasm, { codeHighlighter }] =
+ await Promise.all([
+ import('shiki'),
+ import('shiki/wasm').then((m) => m.default),
+ import('./core'),
+ ])
+
const loaded = await getHighlighterCore({
themes: [
import('shiki/themes/github-light.mjs'),
@@ -41,14 +48,15 @@ const highlighterCore = await (async () => {
loadWasm: getWasm,
})
- return loaded
+ return (o: { lang: string; attrs: string; code: string }) =>
+ codeHighlighter(loaded, o)
})()
export const ShikiHighLighter: FC = (props) => {
const { lang: language, content: value, attrs } = props
const highlightedHtml = useMemo(() => {
- return codeHighlighter(highlighterCore, {
+ return codeHighlighter?.({
attrs: attrs || '',
// code: `${value.split('\n')[0].repeat(10)} // [!code highlight]\n${value}`,
code: value,
diff --git a/src/components/ui/code-highlighter/shiki/core.ts b/src/components/ui/code-highlighter/shiki/core.ts
new file mode 100644
index 0000000000..66bb9583ba
--- /dev/null
+++ b/src/components/ui/code-highlighter/shiki/core.ts
@@ -0,0 +1,45 @@
+import type { BundledLanguage } from 'shiki/langs'
+import type { BundledTheme } from 'shiki/themes'
+import type { CodeToHastOptions, HighlighterCore } from 'shiki/types.mjs'
+
+import {
+ transformerMetaHighlight,
+ transformerNotationDiff,
+ transformerNotationHighlight,
+ transformerNotationWordHighlight,
+} from '@shikijs/transformers'
+
+export function codeHighlighter(
+ highlighter: HighlighterCore,
+ {
+ lang,
+ attrs,
+ code,
+ }: {
+ lang: string
+ attrs: string
+ code: string
+ },
+) {
+ const codeOptions: CodeToHastOptions = {
+ lang,
+ meta: {
+ __raw: attrs,
+ },
+ themes: {
+ light: 'github-light',
+ dark: 'github-dark',
+ },
+ }
+
+ return highlighter.codeToHtml(code, {
+ ...codeOptions,
+ transformers: [
+ ...(codeOptions.transformers || []),
+ transformerNotationDiff(),
+ transformerNotationHighlight(),
+ transformerNotationWordHighlight(),
+ transformerMetaHighlight(),
+ ],
+ })
+}
diff --git a/src/components/ui/code-highlighter/shiki/utils.tsx b/src/components/ui/code-highlighter/shiki/utils.tsx
index 905d8bf200..6d5d6df064 100644
--- a/src/components/ui/code-highlighter/shiki/utils.tsx
+++ b/src/components/ui/code-highlighter/shiki/utils.tsx
@@ -1,52 +1,3 @@
-import type {
- BundledLanguage,
- BundledTheme,
- CodeToHastOptions,
- HighlighterCore,
-} from 'shiki'
-
-import {
- transformerMetaHighlight,
- transformerNotationDiff,
- transformerNotationHighlight,
- transformerNotationWordHighlight,
-} from '@shikijs/transformers'
-
-export function codeHighlighter(
- highlighter: HighlighterCore,
- {
- lang,
- attrs,
- code,
- }: {
- lang: string
- attrs: string
- code: string
- },
-) {
- const codeOptions: CodeToHastOptions = {
- lang,
- meta: {
- __raw: attrs,
- },
- themes: {
- light: 'github-light',
- dark: 'github-dark',
- },
- }
-
- return highlighter.codeToHtml(code, {
- ...codeOptions,
- transformers: [
- ...(codeOptions.transformers || []),
- transformerNotationDiff(),
- transformerNotationHighlight(),
- transformerNotationWordHighlight(),
- transformerMetaHighlight(),
- ],
- })
-}
-
export const parseFilenameFromAttrs = (attrs: string) => {
// filename=""
diff --git a/src/queries/definition/comment.ts b/src/queries/definition/comment.ts
index a77bfe0ff8..a45a386af5 100644
--- a/src/queries/definition/comment.ts
+++ b/src/queries/definition/comment.ts
@@ -1,13 +1,10 @@
-import { useMutation, useQueryClient } from '@tanstack/react-query'
-import { produce } from 'immer'
-import { useSearchParams } from 'next/navigation'
-import type { CommentModel, PaginateResult } from '@mx-space/api-client'
-import type { InfiniteData, MutationOptions } from '@tanstack/react-query'
-
-import { CommentState } from '@mx-space/api-client'
+import type {
+ CommentModel,
+ CommentState,
+ PaginateResult,
+} from '@mx-space/api-client'
import { apiClient } from '~/lib/request'
-import { toast } from '~/lib/toast'
import { defineQuery } from '../helper'
@@ -30,104 +27,3 @@ export const commentAdmin = {
},
}),
}
-
-const useGetCurrentCommentStateFromQuery = () => {
- const search = useSearchParams()
- const state = search.get('tab') as any as CommentState
- return state || CommentState.Unread
-}
-export const useUpdateCommentStateMutation = (
- options?: MutationOptions,
-) => {
- const queryClient = useQueryClient()
-
- const state = useGetCurrentCommentStateFromQuery()
- return useMutation({
- mutationKey: ['comment', 'updateState'],
- mutationFn: async ({ id, state }: { id: string; state: CommentState }) => {
- return apiClient.proxy.comments(id).patch({ data: { state } })
- },
- onMutate: async ({ id }) => {
- queryClient.setQueryData>>(
- commentAdmin.byState(state).queryKey,
- produce((draft) => {
- draft?.pages.forEach((page) => {
- page.data = page.data.filter((comment) => comment.id !== id)
- })
- }),
- )
- },
- onSuccess: (...rest) => {
- options?.onSuccess?.apply(null, rest as any)
- toast.success('操作成功')
- },
- onError: () => {
- toast.error('操作失败')
- },
- })
-}
-
-export const useDeleteCommentMutation = (options?: MutationOptions) => {
- const queryClient = useQueryClient()
- const state = useGetCurrentCommentStateFromQuery()
-
- return useMutation({
- mutationKey: ['comment', 'delete'],
- mutationFn: async ({ id }: { id: string }) => {
- return apiClient.proxy.comments(id).delete()
- },
- onMutate: async ({ id }) => {
- queryClient.setQueryData>>(
- commentAdmin.byState(state).queryKey,
- produce((draft) => {
- draft?.pages.forEach((page) => {
- page.data = page.data.filter((comment) => comment.id !== id)
- })
- }),
- )
- },
- onSuccess: (...rest) => {
- toast.success('删除成功')
- options?.onSuccess?.apply(null, rest as any)
- },
- onError: () => {
- toast.error('删除失败')
- },
- })
-}
-
-export const useReplyCommentMutation = () => {
- const queryClient = useQueryClient()
- const state = useGetCurrentCommentStateFromQuery()
-
- return useMutation({
- mutationKey: ['comment', 'reply'],
- mutationFn: async ({ id, content }: { id: string; content: string }) => {
- return apiClient.proxy.comments.master.reply(id).post({
- data: {
- text: content,
- },
- })
- },
- onMutate({ id }) {
- queryClient.setQueryData>>(
- commentAdmin.byState(state).queryKey,
- produce((draft) => {
- draft?.pages.forEach((page) => {
- page.data = page.data.filter((comment) => comment.id !== id)
- })
- }),
- )
- },
- onSuccess: (_) => {
- toast.success('回复成功')
- },
- onError: () => {
- queryClient.invalidateQueries({
- queryKey: commentAdmin.byState(state).queryKey,
- })
-
- toast.error('回复失败')
- },
- })
-}
diff --git a/src/queries/hooks/comment.ts b/src/queries/hooks/comment.ts
new file mode 100644
index 0000000000..478d44ed9d
--- /dev/null
+++ b/src/queries/hooks/comment.ts
@@ -0,0 +1,113 @@
+import { useMutation, useQueryClient } from '@tanstack/react-query'
+import { produce } from 'immer'
+import { useSearchParams } from 'next/navigation'
+import type { CommentModel, PaginateResult } from '@mx-space/api-client'
+import type { InfiniteData, MutationOptions } from '@tanstack/react-query'
+
+import { CommentState } from '@mx-space/api-client'
+
+import { apiClient } from '~/lib/request'
+import { toast } from '~/lib/toast'
+
+import { commentAdmin } from '../definition/comment'
+
+const useGetCurrentCommentStateFromQuery = () => {
+ const search = useSearchParams()
+ const state = search.get('tab') as any as CommentState
+ return state || CommentState.Unread
+}
+export const useUpdateCommentStateMutation = (
+ options?: MutationOptions,
+) => {
+ const queryClient = useQueryClient()
+
+ const state = useGetCurrentCommentStateFromQuery()
+ return useMutation({
+ mutationKey: ['comment', 'updateState'],
+ mutationFn: async ({ id, state }: { id: string; state: CommentState }) => {
+ return apiClient.proxy.comments(id).patch({ data: { state } })
+ },
+ onMutate: async ({ id }) => {
+ queryClient.setQueryData>>(
+ commentAdmin.byState(state).queryKey,
+ produce((draft) => {
+ draft?.pages.forEach((page) => {
+ page.data = page.data.filter((comment) => comment.id !== id)
+ })
+ }),
+ )
+ },
+ onSuccess: (...rest) => {
+ options?.onSuccess?.apply(null, rest as any)
+ toast.success('操作成功')
+ },
+ onError: () => {
+ toast.error('操作失败')
+ },
+ })
+}
+
+export const useDeleteCommentMutation = (options?: MutationOptions) => {
+ const queryClient = useQueryClient()
+ const state = useGetCurrentCommentStateFromQuery()
+
+ return useMutation({
+ mutationKey: ['comment', 'delete'],
+ mutationFn: async ({ id }: { id: string }) => {
+ return apiClient.proxy.comments(id).delete()
+ },
+ onMutate: async ({ id }) => {
+ queryClient.setQueryData>>(
+ commentAdmin.byState(state).queryKey,
+ produce((draft) => {
+ draft?.pages.forEach((page) => {
+ page.data = page.data.filter((comment) => comment.id !== id)
+ })
+ }),
+ )
+ },
+ onSuccess: (...rest) => {
+ toast.success('删除成功')
+ options?.onSuccess?.apply(null, rest as any)
+ },
+ onError: () => {
+ toast.error('删除失败')
+ },
+ })
+}
+
+export const useReplyCommentMutation = () => {
+ const queryClient = useQueryClient()
+ const state = useGetCurrentCommentStateFromQuery()
+
+ return useMutation({
+ mutationKey: ['comment', 'reply'],
+ mutationFn: async ({ id, content }: { id: string; content: string }) => {
+ return apiClient.proxy.comments.master.reply(id).post({
+ data: {
+ text: content,
+ },
+ })
+ },
+ onMutate({ id }) {
+ queryClient.setQueryData>>(
+ commentAdmin.byState(state).queryKey,
+ produce((draft) => {
+ draft?.pages.forEach((page) => {
+ page.data = page.data.filter((comment) => comment.id !== id)
+ })
+ }),
+ )
+ },
+ onSuccess: (_) => {
+ toast.success('回复成功')
+ },
+ onError: () => {
+ queryClient.invalidateQueries({
+ queryKey: commentAdmin.byState(state).queryKey,
+ })
+
+ toast.error('回复失败')
+ },
+ })
+}