diff --git a/package.json b/package.json index 15e8a622..734f90e3 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "doomslayer", "packageManager": "yarn@4.12.0", "devDependencies": { - "@alauda/doom": "^1.12.7", + "@alauda/doom": "^1.18.2", "@tailwindcss/postcss": "^4.1.12", "@ts-stack/markdown": "^1.5.0", "autoprefixer": "^10.4.21", diff --git a/styles/doc-layout.css b/styles/doc-layout.css new file mode 100644 index 00000000..f5be2737 --- /dev/null +++ b/styles/doc-layout.css @@ -0,0 +1,205 @@ +:root { + --rp-z-index-nav-screen: 70; + --rp-z-index-nav: 60; + --rp-z-index-mask: 20; + --rp-z-index-sidebar: 50; + --rp-z-index-sidebar-menu: 30; + --rp-z-index-aside: 40; + --rp-sidebar-width: 320px; + --rp-sidebar-menu-height: 46px; + --rp-sidebar-padding: 20px; + --rp-outline-width: 268px; + --rp-content-padding-x: 80px; + --rp-content-padding-y: 48px; + --rp-content-max-width: 1000px; + --rp-doc-content-max-width: 1280px; + --rp-sidebar-margin-left: calc( + max( + 0px, + calc((100vw - var(--rp-content-max-width)) / 2 - var(--rp-sidebar-width)) + ) + ); + --rp-outline-margin-right: calc( + max( + 0px, + calc((100vw - var(--rp-content-max-width)) / 2 - var(--rp-outline-width)) + ) + ); +} + +@media (width >= 1280px) { + html:root { + --rp-sidebar-menu-height: 0px; + } +} + +.rp-doc-layout__container { + flex-direction: row; + justify-content: center !important; + width: 100%; + margin: 0; + padding: 0; + display: flex; + position: relative; +} + +.rp-doc-layout__doc { + flex-direction: column; + width: 100%; + display: flex; + position: relative; + overflow-x: auto; +} + +.rp-doc-layout__overview { + width: 100%; + max-width: min(100%, 1280px); + min-height: 60vh; + padding: var(--rp-content-padding-y) var(--rp-content-padding-x); + position: relative; + overflow-x: auto; +} + +.rp-doc-layout__sidebar { + width: var(--rp-sidebar-width); + max-width: var(--rp-sidebar-width); + min-width: var(--rp-sidebar-width); + height: calc(100vh - var(--rp-nav-height) - var(--rp-banner-height, 0px)); + max-height: calc(100vh - var(--rp-nav-height) - var(--rp-banner-height, 0px)); + padding: var(--rp-sidebar-padding); + border-right: 1px solid var(--rp-c-divider-light); + margin-top: calc(-1 * var(--rp-sidebar-menu-height)); + top: calc(var(--rp-nav-height) + var(--rp-banner-height, 0px)); + z-index: var(--rp-z-index-sidebar); + background: var(--rp-c-bg); + position: sticky; + bottom: 0; + left: 0; + overflow: auto scroll; +} + +.rp-doc-layout__doc-container { + min-height: 60vh; + padding: var(--rp-content-padding-y) var(--rp-content-padding-x); +} + +.rp-doc-layout__outline { + width: var(--rp-outline-width); + top: calc(var(--rp-nav-height) + var(--rp-banner-height, 0px)); + margin-top: var(--rp-sidebar-menu-height); + z-index: var(--rp-z-index-aside); + padding-top: var(--rp-content-padding-y); + scrollbar-width: none; + max-height: calc(100vh - var(--rp-nav-height) - var(--rp-banner-height, 0px)); + box-shadow: var(--rp-shadow-1); + position: sticky; + right: 0; + overflow: hidden scroll; +} + +.rp-doc-layout__menu { + top: calc(var(--rp-nav-height) + var(--rp-banner-height, 0px)); + z-index: var(--rp-z-index-sidebar-menu); + height: var(--rp-sidebar-menu-height); + position: sticky; + left: 0; +} + +.rp-doc-layout__menu__placeholder { + width: 100%; + height: var(--rp-sidebar-menu-height); + min-height: var(--rp-sidebar-menu-height); + display: block; +} + +@media (width >= 1280px) { + .rp-doc-layout__doc { + max-width: min(100%, 1280px) !important; + flex: 1; + overflow-x: auto; + } + + .rp-doc-layout__doc--wide { + max-width: min( + 100%, + var(--rp-content-max-width) + var(--rp-sidebar-width) + + var(--rp-outline-width) + ); + } + + .rp-doc-layout__sidebar { + margin-left: var(--rp-sidebar-margin-left); + } + + .rp-doc-layout__sidebar-placeholder { + width: var(--rp-sidebar-width); + margin-left: var(--rp-sidebar-margin-left); + } + + .rp-doc-layout__outline { + margin-right: 0 !important; + padding-bottom: var(--rp-content-padding-y); + } + + .rp-doc-layout__outline-placeholder { + width: var(--rp-outline-width); + margin-right: var(--rp-outline-margin-right); + } +} + +@media (width <= 1279px) { + :root { + --rp-content-padding-x: 36px; + --rp-content-padding-y: 48px; + } + + .rp-doc-layout__outline { + background-color: color-mix(in srgb, var(--rp-c-bg) 60%, transparent); + backdrop-filter: blur(25px); + border-radius: var(--rp-radius-small); + max-width: 100%; + box-shadow: var(--rp-shadow-2); + visibility: hidden; + opacity: 0; + padding: 20px 0; + transition: opacity 0.2s, transform 0.2s cubic-bezier(0.19, 1, 0.22, 1); + position: fixed; + inset-inline-end: 0; + transform: translate3d(0, -10px, 0); + } + + .rp-doc-layout__outline--open { + opacity: 1; + visibility: visible; + display: block; + transform: translate3d(0, 0, 0); + } +} + +@media (width <= 768px) { + :root { + --rp-content-padding-x: 24px; + } + + .rp-doc-layout__sidebar { + z-index: var(--rp-z-index-sidebar); + top: calc(var(--rp-nav-height) + var(--rp-banner-height, 0px)); + height: calc(100vh - var(--rp-nav-height)); + padding: var(--rp-sidebar-padding) var(--rp-sidebar-padding) + calc(var(--rp-sidebar-padding) + 100px) var(--rp-sidebar-padding); + background: var(--rp-c-bg); + opacity: 0; + margin-top: 0; + transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1); + position: fixed; + overflow: auto scroll; + transform: translate3d(-100%, 0, 0); + } + + .rp-doc-layout__sidebar--open { + opacity: 1; + visibility: visible; + left: 0; + transform: translate3d(0, 0, 0); + } +} diff --git a/styles/index.css b/styles/index.css index 687caa30..7ef289cd 100644 --- a/styles/index.css +++ b/styles/index.css @@ -1,55 +1,198 @@ -@import "tailwindcss"; - -.editLink { - color: var(--rp-c-brand); - text-decoration: none; - font-size: 15px; - font-weight: 500; - transition: all 0.2s ease-in-out; - padding-left: 12px; -} - -.editLink:hover { - color: var(--rp-c-brand-dark); -} - -.paginationItem { - font-weight: 500; - cursor: pointer; - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - - --tw-font-weight: var(--font-weight-medium) /* 500 */; - font-weight: var(--font-weight-medium) /* 500 */; - - margin-inline: calc(var(--spacing) * 1.5) /* 0.375rem = 6px */; - padding-inline: calc(var(--spacing) * 3) /* 0.75rem = 12px */; - padding-block: calc(var(--spacing) * 2) /* 0.5rem = 8px */; - display: flex; - align-items: center; -} - -.paginationItem:hover { - background-color: var(--rp-c-bg-soft); - cursor: pointer; - color: var(--rp-c-brand-dark); - border-radius: 12px; -} - -.paginationItem.active { - background-color: var(--rp-c-bg-soft); - cursor: pointer; - color: var(--rp-c-brand-dark); - border-radius: 12px; -} - -.paginationItem.disabled { - cursor: not-allowed; - color: var(--rp-c-gray); - background-color: transparent; - border: none; -} - -.rp-font-bold { - font-weight: 600; -} +@import "tailwindcss"; +@import "./doc-layout.css"; + +:root { + --rp-nav-height: 60px !important; +} + +.editLink { + color: var(--rp-c-brand); + text-decoration: none; + font-size: 15px; + font-weight: 500; + transition: all 0.2s ease-in-out; + padding-left: 12px; +} + +.editLink:hover { + color: var(--rp-c-brand-dark); +} + +.paginationItem { + font-weight: var(--font-weight-medium); + cursor: pointer; + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + + --tw-font-weight: var(--font-weight-medium) /* 500 */; + + margin-inline: calc(var(--spacing) * 1.5) /* 0.375rem = 6px */; + padding-inline: calc(var(--spacing) * 3) /* 0.75rem = 12px */; + padding-block: calc(var(--spacing) * 2) /* 0.5rem = 8px */; + display: flex; + align-items: center; +} + +.paginationItem:hover { + background-color: var(--rp-c-bg-soft); + cursor: pointer; + color: var(--rp-c-brand-dark); + border-radius: var(--rp-radius); +} + +.paginationItem.active { + background-color: var(--rp-c-bg-soft); + cursor: pointer; + color: var(--rp-c-brand-dark); + border-radius: var(--rp-radius); +} + +.paginationItem.disabled { + cursor: not-allowed; + color: var(--rp-c-gray); + background-color: transparent; + border: none; +} + +.rp-font-bold { + font-weight: 600; +} + +.card { + display: block; + border: 1px solid var(--rp-c-divider-light); + border-radius: var(--rp-radius); + background-color: var(--rp-c-bg); + padding: 1rem; +} + +.card__title { + font-size: 1.125rem; + font-weight: 600; + margin-bottom: 0.75rem; + color: var(--rp-c-text-1); +} + +.card__content { + color: var(--rp-c-text-2); +} + +.link-card { + display: block; + border-bottom: 1px solid var(--rp-c-divider-light); + background-color: var(--rp-c-bg); + padding: 1.25rem; + text-decoration: none; + transition-property: color, background-color, border-color; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.link-card:hover { + background-color: var(--rp-c-bg-soft); +} + +.link-card__title { + font-size: 1.125rem; + font-weight: 600; + margin-bottom: 0.5rem; + color: var(--rp-c-text-1); + line-height: 1.75rem; +} + +.link-card__description { + color: var(--rp-c-text-2); + font-size: 0.875rem; + line-height: 1.5rem; +} + +.post-meta { + display: flex; + font-size: 0.875rem; + color: var(--rp-c-text-3); + line-height: 1.5rem; + font-weight: 500; +} + +@media (min-width: 640px) { + .post-meta { + line-height: 2rem; + } +} + +.breadcrumb { + margin-bottom: 2.5rem; +} + +.home-footer { + margin-top: 3rem; + padding-top: 2rem; + padding-bottom: 2rem; + padding-left: 1.5rem; + padding-right: 1.5rem; + width: 100%; + border-top: 1px solid var(--rp-c-divider-light); +} + +@media (min-width: 640px) { + .home-footer { + padding: 2rem; + } +} + +.home-footer__content { + margin: auto; + width: 100%; + text-align: center; + font-weight: 500; + font-size: 0.875rem; + color: var(--rp-c-text-2); +} + +.rp-doc-layout__menu { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + background-color: var(--rp-c-bg); + border-bottom: 1px solid var(--rp-c-divider-light); + padding: 0.75rem 1rem; + align-items: center; + gap: 0.5rem; +} + +@media (max-width: 1280px) { + .rp-doc-layout__menu { + display: flex; + } +} + +.rp-doc-layout__menu-button { + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + padding: 0; + border: none; + background: transparent; + color: var(--rp-c-text-1); + cursor: pointer; + border-radius: var(--rp-radius); + transition: background-color 0.2s; +} + +.rp-doc-layout__menu-button:hover { + background-color: var(--rp-c-bg-soft); +} + +.rp-doc-layout__menu-button:active { + background-color: var(--rp-c-bg-mute); +} + +.rp-doc-layout__menu-button svg { + width: 100%; + height: 100%; +} diff --git a/theme/components/BreadCrumb/index.tsx b/theme/components/BreadCrumb/index.tsx index adf6d38c..a2fce578 100644 --- a/theme/components/BreadCrumb/index.tsx +++ b/theme/components/BreadCrumb/index.tsx @@ -4,7 +4,7 @@ import { useMemo } from "react"; export const BreadCrumb = () => { const { page, siteData } = usePageData(); const { base } = siteData; - const t = useI18n(); + const t = useI18n(); const href = useMemo(() => { if (!base) { @@ -14,7 +14,7 @@ export const BreadCrumb = () => { }, [page, base]); return ( -
+
{t("knowledge_title")} diff --git a/theme/components/Card/index.tsx b/theme/components/Card/index.tsx new file mode 100644 index 00000000..03ad4366 --- /dev/null +++ b/theme/components/Card/index.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +export interface CardProps { + title?: string; + content?: React.ReactNode; + style?: React.CSSProperties; + className?: string; + children?: React.ReactNode; +} + +export const Card: React.FC = ({ + title, + content, + style, + className = "", + children, +}) => { + return ( +
+ {title &&
{title}
} + {(content || children) && ( +
{content || children}
+ )} +
+ ); +}; diff --git a/theme/components/Checkbox/index.tsx b/theme/components/Checkbox/index.tsx index 59ff696d..0e458609 100644 --- a/theme/components/Checkbox/index.tsx +++ b/theme/components/Checkbox/index.tsx @@ -1,5 +1,4 @@ import { forwardRef, useCallback } from "react"; -import { useI18n } from "rspress/runtime"; export interface CheckboxProps { label: string; @@ -40,7 +39,10 @@ export default forwardRef( onChange={handleChange} disabled={disabled} className={` - w-4 h-4 + w-[16px] h-[16px] + min-w-[16px] min-h-[16px] + max-w-[16px] max-h-[16px] + flex-shrink-0 rounded border border-gray-300 bg-white diff --git a/theme/components/DocID/index.tsx b/theme/components/DocID/index.tsx index 5967ea04..5b9711a6 100644 --- a/theme/components/DocID/index.tsx +++ b/theme/components/DocID/index.tsx @@ -8,7 +8,7 @@ export const DocID = ({ id }: { id?: string }) => { return id || (pageData.page.frontmatter.id as string); }, [id, pageData]); return docID ? ( -
+
ID: {docID}
) : ( diff --git a/theme/components/EditOnGithub/index.tsx b/theme/components/EditOnGithub/index.tsx index 2f49523a..7209ad78 100644 --- a/theme/components/EditOnGithub/index.tsx +++ b/theme/components/EditOnGithub/index.tsx @@ -43,7 +43,7 @@ function EditIcon() { export const EditOnGithub = () => { const { editLink, issueLink } = useEditLink(); - const t = useI18n(); + const t = useI18n(); return (
diff --git a/theme/components/Empty/index.tsx b/theme/components/Empty/index.tsx index 0bcb2b96..49054846 100644 --- a/theme/components/Empty/index.tsx +++ b/theme/components/Empty/index.tsx @@ -1,4 +1,4 @@ -import { useThemeState } from "@rspress/core/theme"; +import { useThemeState } from "@rspress/core/theme-original"; import React from "react"; interface EmptyStateProps { diff --git a/theme/components/HomeBanner/index.tsx b/theme/components/HomeBanner/index.tsx index aa1aed21..132da9a7 100644 --- a/theme/components/HomeBanner/index.tsx +++ b/theme/components/HomeBanner/index.tsx @@ -1,4 +1,4 @@ -import { useI18n, usePageData } from "@rspress/runtime"; +import { useI18n } from "@rspress/core/runtime"; interface StyledProps { className?: string; @@ -9,8 +9,7 @@ interface BannerProps extends StyledProps { } export const HomeBanner: React.FC = ({ className }) => { - const pageData = usePageData(); - const t = useI18n(); + const t = useI18n(); // const logo = // typeof pageData.siteData.logo === "string" diff --git a/theme/components/HomeContent/index.tsx b/theme/components/HomeContent/index.tsx index d83df267..d72972c9 100644 --- a/theme/components/HomeContent/index.tsx +++ b/theme/components/HomeContent/index.tsx @@ -1,5 +1,5 @@ import { useI18n, usePageData } from "@rspress/core/runtime"; -import { Card, useFullTextSearch } from "@rspress/core/theme"; +import { useFullTextSearch } from "@rspress/core/theme-original"; import { useCallback, useEffect, useMemo, useState } from "react"; import { PostInfo, postInfos } from "virtual-post-data"; @@ -13,10 +13,12 @@ import { usePersistSearchParams, useSessionStorage, } from "../../hooks/SessionStorage"; +import { Card } from "../Card"; import Checkbox from "../Checkbox"; import Pagination from "../Pagination"; import { PostList } from "../PostList"; import Search from "../Search"; +import React from "react"; const SEARCHED_LIMIT = 1000; const PAGE_SIZE = 10; @@ -37,7 +39,7 @@ export const HomeContent: React.FC = () => { const [searchedPosts, setSearchedPosts] = useState([]); const { page, siteData } = usePageData(); const [searchInitialized, setSearchInitialized] = useState([]); - const t = useI18n(); + const t = useI18n(); const searchFull = useCallback( async (keyword: string) => { diff --git a/theme/components/LinkCard/index.tsx b/theme/components/LinkCard/index.tsx new file mode 100644 index 00000000..f4525700 --- /dev/null +++ b/theme/components/LinkCard/index.tsx @@ -0,0 +1,25 @@ +import React from "react"; + +export interface LinkCardProps { + href: string; + title: string; + description?: React.ReactNode; + style?: React.CSSProperties; + className?: string; +} + +export const LinkCard: React.FC = ({ + href, + title, + description, + style, + className = "", +}) => { + return ( + +
{title}
+ {description &&
{description}
} +
+ ); +}; + diff --git a/theme/components/Pagination/index.tsx b/theme/components/Pagination/index.tsx index cf1882da..de8952d3 100644 --- a/theme/components/Pagination/index.tsx +++ b/theme/components/Pagination/index.tsx @@ -15,7 +15,7 @@ interface PageItem { const Pagination = ({ currentPage, totalPage, onChange }: PaginationProps) => { const neighBorsNumber = 1; - const t = useI18n(); + const t = useI18n(); const paginationItems = useMemo(() => { const items: Array = []; diff --git a/theme/components/PostList/index.tsx b/theme/components/PostList/index.tsx index 9a096b38..fab75786 100644 --- a/theme/components/PostList/index.tsx +++ b/theme/components/PostList/index.tsx @@ -1,11 +1,12 @@ import { Markdown } from "@alauda/doom/runtime"; -import { useI18n, useLocaleSiteData, usePageData } from "@rspress/core/runtime"; -import { Badge, LinkCard } from "@rspress/core/theme"; +import { useI18n, usePageData } from "@rspress/core/runtime"; +import { Badge } from "@rspress/core/theme-original"; import { FC, useMemo } from "react"; import { PostInfo } from "../../../plugins/plugin-post-resolver"; import { DocID } from "../DocID"; import EmptyState from "../Empty"; +import { LinkCard } from "../LinkCard"; interface PostListProps { postList: PostInfo[]; @@ -13,19 +14,12 @@ interface PostListProps { export const PostList: FC = ({ postList }) => { const notEmpty = useMemo(() => postList.length > 0, [postList]); - const t = useI18n(); + const t = useI18n(); const { siteData } = usePageData(); const { base } = siteData; - const { lastUpdatedText: localesLastUpdatedText = "Last Updated" } = - useLocaleSiteData(); - - const { themeConfig } = siteData; - const lastUpdatedText = - themeConfig?.lastUpdatedText || localesLastUpdatedText; - return (
{notEmpty ? ( @@ -52,9 +46,10 @@ export const PostList: FC = ({ postList }) => { ))}
-
+

- {lastUpdatedText}: {post.lastUpdatedTime} + {t("lastUpdatedText")}:{" "} + {post.lastUpdatedTime}

diff --git a/theme/components/SidebarMenu/index.ts b/theme/components/SidebarMenu/index.ts new file mode 100644 index 00000000..aa25bad2 --- /dev/null +++ b/theme/components/SidebarMenu/index.ts @@ -0,0 +1,2 @@ +export { useSidebarMenu } from './useSidebarMenu'; + diff --git a/theme/components/SidebarMenu/useSidebarMenu.tsx b/theme/components/SidebarMenu/useSidebarMenu.tsx new file mode 100644 index 00000000..828be380 --- /dev/null +++ b/theme/components/SidebarMenu/useSidebarMenu.tsx @@ -0,0 +1,62 @@ +import { useRef, useState } from "react"; +import { useI18n } from "@rspress/core/runtime"; +import { + useDynamicToc, + ReadPercent, + SvgWrapper, + IconArrowRight, +} from "@rspress/core/theme-original"; + +export function useSidebarMenu() { + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + const [isOutlineOpen, setIsOutlineOpen] = useState(false); + const sidebarLayoutRef = useRef(null); + const asideLayoutRef = useRef(null); + + const headers = useDynamicToc(); + const t = useI18n(); + + const toggleOutline = () => { + setIsOutlineOpen((prev) => !prev); + if (isSidebarOpen) { + setIsSidebarOpen(false); + } + }; + + const sidebarMenu = ( +
+ +
+ ); + + return { + isSidebarOpen, + isOutlineOpen, + sidebarMenu, + asideLayoutRef, + sidebarLayoutRef, + toggleOutline, + }; +} diff --git a/theme/index.tsx b/theme/index.tsx index c81f1aa9..d9615277 100644 --- a/theme/index.tsx +++ b/theme/index.tsx @@ -1,6 +1,11 @@ import Layout from "./layout"; import HomeLayout from "./layout/HomeLayout"; +import { DocLayout } from "./layout/DocLayout"; -export { HomeLayout, Layout }; +export { HomeLayout, Layout, DocLayout }; -export * from "@rspress/core/theme"; +export * from "@rspress/core/theme-original"; + +// 导出本地实现的组件 +export { Card } from "./components/Card"; +export { LinkCard } from "./components/LinkCard"; diff --git a/theme/layout/DocLayout/index.tsx b/theme/layout/DocLayout/index.tsx new file mode 100644 index 00000000..fafce408 --- /dev/null +++ b/theme/layout/DocLayout/index.tsx @@ -0,0 +1,143 @@ +import { useFrontmatter } from '@rspress/core/runtime'; +import { + DocContent, + DocFooter, + Outline, + Overview, + useWatchToc, +} from '@rspress/core/theme-original'; +import clsx from 'clsx'; +import React from 'react'; +import { useSidebarMenu } from '../../components/SidebarMenu'; + +export interface DocLayoutProps { + beforeSidebar?: React.ReactNode; + afterSidebar?: React.ReactNode; + beforeDocFooter?: React.ReactNode; + afterDocFooter?: React.ReactNode; + beforeDoc?: React.ReactNode; + afterDoc?: React.ReactNode; + beforeDocContent?: React.ReactNode; + afterDocContent?: React.ReactNode; + beforeOutline?: React.ReactNode; + afterOutline?: React.ReactNode; + navTitle?: React.ReactNode; + components?: Record; +} + +export function DocLayout(props: DocLayoutProps) { + const { + beforeDocFooter, + afterDocFooter, + beforeDoc, + afterDoc, + beforeDocContent, + afterDocContent, + beforeOutline, + afterOutline, + components, + } = props; + const { frontmatter } = useFrontmatter(); + + const isOverviewPage = frontmatter?.overview ?? false; + + const showDocFooter = false; + + const { outline: showOutline = true, pageType } = frontmatter || {}; + + const isDocWide = pageType === 'doc-wide'; + + const { + isOutlineOpen, + sidebarMenu, + asideLayoutRef, + } = useSidebarMenu(); + + const { rspressDocRef } = useWatchToc(); + + return ( + <> +
{sidebarMenu}
+ {beforeDoc} +
+ {/* Sidebar - 强制隐藏 */} + {/* {showSidebar ? ( + + ) : ( + + )} */} + + {/* Main document content */} + {isOverviewPage ? ( + <> +
+ {beforeDocContent} + } + /> + {afterDocContent} +
+ + ) : ( +
+
+ {beforeDocContent} +
+ +
+ {afterDocContent} + {beforeDocFooter} + {/* DocFooter - 强制隐藏 */} + {showDocFooter && } + {afterDocFooter} +
+
+ )} + + {/* Right outline - 保留,可通过 frontmatter 控制 */} + {isOverviewPage ? null : showOutline ? ( + + ) : ( + + )} +
+ + {afterDoc} + + ); +} + diff --git a/theme/layout/HomeLayout/index.tsx b/theme/layout/HomeLayout/index.tsx index 7ccb9fcc..07559b4f 100644 --- a/theme/layout/HomeLayout/index.tsx +++ b/theme/layout/HomeLayout/index.tsx @@ -1,8 +1,9 @@ -import { usePageData } from "@rspress/runtime"; +import { usePageData } from "@rspress/core/runtime"; import { ReactNode } from "react"; import { HomeBanner } from "../../components/HomeBanner"; import { HomeContent } from "../../components/HomeContent"; +import React from "react"; const HomeLayout: React.FC<{ children: ReactNode }> = ({ children }) => { return ( @@ -20,9 +21,8 @@ export default () => { -