From 9e800ada9f3d82b8f22a6ea6a8a41cfc2965874b Mon Sep 17 00:00:00 2001 From: sanyuan <494130947@qq.com> Date: Sat, 15 Oct 2022 22:34:27 +0800 Subject: [PATCH] feat: custom theme doc --- docs/.island/config.ts | 16 +- docs/en/api/api-runtime.mdx | 19 ++ docs/en/api/api-theme.md | 68 ++++++ docs/en/api/config-theme.mdx | 2 +- docs/en/fragments/content.mdx | 13 ++ docs/en/fragments/{locales.md => locales.mdx} | 0 docs/en/fragments/route-hook.mdx | 10 + docs/en/fragments/use-page-data.mdx | 45 ++++ docs/en/guide/custom-theme.md | 3 - docs/en/guide/custom-theme.mdx | 193 ++++++++++++++++++ docs/en/guide/i18n.mdx | 2 +- docs/zh/api/api-runtime.mdx | 19 ++ docs/zh/api/api-theme.md | 67 ++++++ docs/zh/api/config-theme.mdx | 2 +- docs/zh/fragments/content.mdx | 13 ++ docs/zh/fragments/{locales.md => locales.mdx} | 0 docs/zh/fragments/route-hook.mdx | 10 + docs/zh/fragments/use-page-data.mdx | 45 ++++ docs/zh/guide/custom-theme.md | 3 - docs/zh/guide/custom-theme.mdx | 190 +++++++++++++++++ docs/zh/guide/i18n.mdx | 2 +- package.json | 4 +- src/runtime/index.ts | 1 + src/theme-default/components/Aside/index.tsx | 7 +- src/theme-default/layout/DocLayout/index.tsx | 20 +- src/theme-default/layout/Layout/index.tsx | 2 +- 26 files changed, 737 insertions(+), 19 deletions(-) create mode 100644 docs/en/api/api-runtime.mdx create mode 100644 docs/en/api/api-theme.md create mode 100644 docs/en/fragments/content.mdx rename docs/en/fragments/{locales.md => locales.mdx} (100%) create mode 100644 docs/en/fragments/route-hook.mdx create mode 100644 docs/en/fragments/use-page-data.mdx delete mode 100644 docs/en/guide/custom-theme.md create mode 100644 docs/en/guide/custom-theme.mdx create mode 100644 docs/zh/api/api-runtime.mdx create mode 100644 docs/zh/api/api-theme.md create mode 100644 docs/zh/fragments/content.mdx rename docs/zh/fragments/{locales.md => locales.mdx} (100%) create mode 100644 docs/zh/fragments/route-hook.mdx create mode 100644 docs/zh/fragments/use-page-data.mdx delete mode 100644 docs/zh/guide/custom-theme.md create mode 100644 docs/zh/guide/custom-theme.mdx diff --git a/docs/.island/config.ts b/docs/.island/config.ts index 9af8b695..77d162ed 100644 --- a/docs/.island/config.ts +++ b/docs/.island/config.ts @@ -17,8 +17,7 @@ export default defineConfig({ }, markdown: { rehypePlugins: [], - remarkPlugins: [], - lineNumbers: true + remarkPlugins: [] }, route: { exclude: ['custom.tsx', '**/fragments/**'] @@ -197,6 +196,19 @@ function getSidebar(lang: 'zh' | 'en') { link: getLink('/api/config-extension') } ] + }, + { + text: getText('Client API', 'Client API'), + items: [ + { + text: getText('运行时 API', 'Runtime API'), + link: getLink('/api/api-runtime') + }, + { + text: getText('默认主题', 'Default Theme'), + link: getLink('/api/api-theme') + } + ] } ] }; diff --git a/docs/en/api/api-runtime.mdx b/docs/en/api/api-runtime.mdx new file mode 100644 index 00000000..cc92e439 --- /dev/null +++ b/docs/en/api/api-runtime.mdx @@ -0,0 +1,19 @@ +# Runtime API + +import UsePageData from '../fragments/use-page-data.mdx'; +import Content from '../fragments/content.mdx'; +import RouteHook from '../fragments/route-hook.mdx'; + +In the process of theme development, we generally need the following key APIs to obtain page data or status: + +## `usePageData` + + + +## Content + + + +## 路由 Hook + + diff --git a/docs/en/api/api-theme.md b/docs/en/api/api-theme.md new file mode 100644 index 00000000..ac2ba4eb --- /dev/null +++ b/docs/en/api/api-theme.md @@ -0,0 +1,68 @@ +# Default Theme API + +The default theme contains a series of components, you can implement custom themes by overriding or extending these components. + +## Layout + +The `Layout` component is the entry point component of the theme, which is used by Island.js to render the layout of the entire documentation site. + +```tsx +// theme/index.tsx +import { Layout } from 'islandjs'; +``` + +It provides a series of slots through Props to achieve expansion, and the types are defined as follows: + +```tsx +interface LayoutProps { + /* Before home hero */ + beforeHero?: React.ReactNode; + /* After home hero */ + afterHero?: React.ReactNode; + /* Before home features */ + beforeFeatures?: React.ReactNode; + /* After home features */ + afterFeatures?: React.ReactNode; + /* Before doc footer */ + beforeDocFooter?: React.ReactNode; + /* Doc page front */ + beforeDoc?: React.ReactNode; + /* Doc page end */ + afterDoc?: React.ReactNode; + /* Before the title of the navigation bar in the upper left corner */ + beforeNavTitle?: React.ReactNode; + /* After the title of the navigation bar in the upper left corner + */ + afterNavTitle?: React.ReactNode; + /* Above the right outline column */ + beforeOutline?: React.ReactNode; + /* Below the outline column on the right */ + afterOutline?: React.ReactNode; + /* Top of the entire page */ + top?: React.ReactNode; + /* Bottom of the entire page */ + bottom?: React.ReactNode; +} +``` + +## HomeLayout + +The `HomeLayout` component is the theme's home page layout component, which is used by Island.js to render the home page layout. + +```tsx +// theme/index.tsx +import { HomeLayout } from 'islandjs'; +``` + +## NotFoundLayout + +The `NotFoundLayout` component is the theme's 404 page layout component, which is used by Island.js to render the 404 page layout. + +## setup + +`setup` is used to add an initialization logic, such as global event binding. + +```tsx +// theme/index.tsx +import { setup } from 'islandjs'; +``` diff --git a/docs/en/api/config-theme.mdx b/docs/en/api/config-theme.mdx index 6e3f1713..0eb88b35 100644 --- a/docs/en/api/config-theme.mdx +++ b/docs/en/api/config-theme.mdx @@ -1,6 +1,6 @@ # Theme Config -import Locales from '../fragments/locales.md'; +import Locales from '../fragments/locales.mdx'; The theme config is under the `themeConfig` in root config. For example: diff --git a/docs/en/fragments/content.mdx b/docs/en/fragments/content.mdx new file mode 100644 index 00000000..0a78c035 --- /dev/null +++ b/docs/en/fragments/content.mdx @@ -0,0 +1,13 @@ +Get the body MDX component content, that is, the doc content: + +```ts +import { Content } from 'islandjs/runtime'; + +function Layout() { + return ( +
+ +
+ ); +} +``` diff --git a/docs/en/fragments/locales.md b/docs/en/fragments/locales.mdx similarity index 100% rename from docs/en/fragments/locales.md rename to docs/en/fragments/locales.mdx diff --git a/docs/en/fragments/route-hook.mdx b/docs/en/fragments/route-hook.mdx new file mode 100644 index 00000000..ae57cb66 --- /dev/null +++ b/docs/en/fragments/route-hook.mdx @@ -0,0 +1,10 @@ +Island.js uses [react-router-dom](https://reactrouter.com/) internally to implement routing, so you can use `react-router-dom` Hook directly, for example: + +```ts +import { useLocation } from 'islandjs/runtime'; + +function Layout() { + const location = useLocation(); + return
Current location: {location.pathname}
; +} +``` diff --git a/docs/en/fragments/use-page-data.mdx b/docs/en/fragments/use-page-data.mdx new file mode 100644 index 00000000..fb8fbc8d --- /dev/null +++ b/docs/en/fragments/use-page-data.mdx @@ -0,0 +1,45 @@ +Hook for the user to get all the data of the page, such as: + +```tsx +import { usePageData } from 'islandjs/runtime'; + +function Layout() { + const pageData = usePageData(); + return
{pageData.title}
; +} +``` + +The type of `usePageData` is as follows: + +```ts +const usePageData: () => PageData; +``` + +The type of `PageData` is as follows: + +```ts +export interface PageData { + // Site general information, including theme configuration themeConfig information + siteData: SiteData; + // Last update time + lastUpdatedTime?: string; + // Page title + title?: string; + // Page description + description?: string; + // Front Matter of the page + frontmatter?: FrontMatterMeta; + // Page type + pageType: PageType; + // TOC data + toc?: Header[]; + // Current route path + routePath: string; + // The path of the page, remove query and hash + pagePath: string; + // Doc content of the page + content?: string; +} +``` + +Based on this API, you can almost get all the data you need. diff --git a/docs/en/guide/custom-theme.md b/docs/en/guide/custom-theme.md deleted file mode 100644 index 7190c150..00000000 --- a/docs/en/guide/custom-theme.md +++ /dev/null @@ -1,3 +0,0 @@ -# Custom Theme - -🚧 This page is still under construction. diff --git a/docs/en/guide/custom-theme.mdx b/docs/en/guide/custom-theme.mdx new file mode 100644 index 00000000..3c294788 --- /dev/null +++ b/docs/en/guide/custom-theme.mdx @@ -0,0 +1,193 @@ +# Custom Theme + +import UsePageData from '../fragments/use-page-data.mdx'; +import Content from '../fragments/content.mdx'; +import RouteHook from '../fragments/route-hook.mdx'; + +Island.js has a built-in set of default themes out of the box, and the internal components also provide config to customize, including: + +- [Navbar](/en/guide/navbar) +- [Home Page](/en/guide/home-page) +- [API Page](/en/guide/api-page) +- [Doc Page](/en/guide/doc-page) +- [Locales](/en/guide/i18n) +- [Search](/en/guide/search) + +You can click on the corresponding page to view specific configuration items. This article is to introduce how to develop a custom theme. + +## Extend default theme + +In most cases, you do not want to develop a theme from scratch, but want to extend it based on the default theme. In this case, you can refer to the following methods for theme development. + +:::tip +If you want to develop a custom theme from scratch, you can go to +[Develop custom theme from scratch](/en/guide/custom-theme#develop-custom-theme-from-scratch)。 +::: + +### 1. Basic Structure + +By default, you need to create a `theme` directory in the `.island` directory, and then create an `index.ts(x)` file in this directory, which is your theme entry file: + +```bash +.island +├── config.ts +└── theme + └── index.tsx +``` + +You can write the `theme/index.tsx` file as follows: + +```ts +// `theme/index.tsx` +import React from 'react'; +import { + Layout as DefaultLayout, + NotFoundLayout, + HomeLayout, + setup +} from 'islandjs/theme'; +// Add some custom styles +import './custom.css'; + +const Layout = () => beforeHero} />; + +// Export the three components and the setup function +export { Layout, HomeLayout, NotFoundLayout, setup }; +``` + +As you can see, you can get and export the various components of the default theme from `islandjs/theme`, including: + +- **Layout component**, the layout component of the page +- **HomeLayout component**, the layout component of the home page, used by the Layout component +- **NotFoundLayout component**, the layout component of the 404 page, used by the Layout component +- Also includes **setup function**, used to add an initialization logic, such as global event binding, which must be exported + +### 2. Use Slot + +It is worth noting that the Layout component has designed a series of props to support slot elements. You can use these props to extend the layout of the default theme. For example, change the above Layout component to the following form: + +```tsx +import { Layout as DefaultLayout } from 'islandjs/theme'; + +// Show all props below +const Layout = () => ( + beforeHero} + /* After home hero */ + afterHero={
afterHero
} + /* Before home features */ + beforeFeatures={
beforeFeatures
} + /* After home features */ + afterFeatures={
afterFeatures
} + /* Before doc footer */ + beforeDocFooter={
beforeDocFooter
} + /* Doc page front */ + beforeDoc={
beforeDoc
} + /* Doc page end */ + afterDoc={
afterDoc
} + /* Before the title of the navigation bar in the upper left corner */ + beforeNavTitle={😄} + /* After the title of the navigation bar in the upper left corner + */ + afterNavTitle={
afterNavTitle
} + /* Above the right outline column */ + beforeOutline={
beforeOutline
} + /* Below the outline column on the right */ + afterOutline={
afterOutline
} + /* Top of the entire page */ + top={
top
} + /* Bottom of the entire page */ + bottom={
bottom
} + /> +); +``` + +### 3. Custom Component + +To extend the components of the default theme, in addition to the slots, you can also customize the Home page and 404 page components, such as: + +```tsx +import { Layout, setup } from 'islandjs/theme'; +// Customize Home Page +const HomeLayout = () =>
Home
; +// Customize 404 page + +const NotFoundLayout = () =>
404
; + +export { Layout, HomeLayout, NotFoundLayout, setup }; +``` + +Of course, you may need to use page data during the development process, you can get it through the [`usePageData`](/en/guide/custom-theme#usepagedata) Hook. + +## Develop custom theme from scratch + +### 1. Basic Structure + +Of course, if you're going to develop a custom theme from scratch, you'll need to understand what makes up a theme. + +By default, you need to create a `theme` directory in the `.island` directory, and then create an `index.ts(x)` file in this directory, which is your theme entry file: + +```bash +.island +├── config.ts +└── theme + └── index.tsx +``` + +In the `theme/index.tsx` file, you need to export a Layout component, which is the entry component of your theme: + +```ts +// theme/index.tsx +function Layout() { + return
Custom Theme Layout
; +} + +// setup function, which will be called when the page is initialized. It is generally used to monitor global events. It can be an empty function. +const setup = () => {}; + +// Export the Layout component and setup function +// Both must be exported +export { Layout, setup }; +``` + +This Layout component will be used by Island.js to render the layout of the entire documentation site. You can import your custom components in this component, such as: + +```ts +// theme/index.tsx +import { Navbar } from './Navbar'; + +function Layout() { + return ( +
+ +
Custom Theme Layout
+
+ ); +} + +export { Layout }; + +// theme/Navbar.tsx +export function Navbar() { + return
Custom Navbar
; +} +``` + +So the question is, how does the theme component get the page data and the content of the body MDX component? This requires the use of the `Runtime API` of Island.js. + +### 2. Integrate Runtime API + +In the process of theme development, we generally need the following key APIs: + +#### usePageData + + + +#### Content + + + +#### Route Hook + + diff --git a/docs/en/guide/i18n.mdx b/docs/en/guide/i18n.mdx index c5618350..8025d74b 100644 --- a/docs/en/guide/i18n.mdx +++ b/docs/en/guide/i18n.mdx @@ -1,6 +1,6 @@ # I18n -import Locales from '../fragments/locales.md'; +import Locales from '../fragments/locales.mdx'; Island.js provides a set of out-of-the-box internationalization solutions. Next, we will introduce how to integrate it in your project. diff --git a/docs/zh/api/api-runtime.mdx b/docs/zh/api/api-runtime.mdx new file mode 100644 index 00000000..f2cb2491 --- /dev/null +++ b/docs/zh/api/api-runtime.mdx @@ -0,0 +1,19 @@ +# Runtime API + +import UsePageData from '../fragments/use-page-data.mdx'; +import Content from '../fragments/content.mdx'; +import RouteHook from '../fragments/route-hook.mdx'; + +在主题开发的过程中,我们一般需要如下的一些关键 API 来获取页面的数据或者状态: + +## `usePageData` + + + +## Content + + + +## 路由 Hook + + diff --git a/docs/zh/api/api-theme.md b/docs/zh/api/api-theme.md new file mode 100644 index 00000000..bb38d082 --- /dev/null +++ b/docs/zh/api/api-theme.md @@ -0,0 +1,67 @@ +# 默认主题 API + +默认主题包含一系列的组件,你可以通过覆盖或者扩展这些组件来实现自定义主题。 + +## Layout + +`Layout` 组件是主题的入口组件,它会被 Island.js 用来渲染整个文档站点的布局。 + +```tsx +// theme/index.tsx +import { Layout } from 'islandjs'; +``` + +它通过 Props 提供了一系列的插槽来实现拓展,类型定义如下: + +```tsx +interface LayoutProps { + /* Home 页 Hero 部分之前 */ + beforeHero?: React.ReactNode; + /* Home 页 Hero 部分之后 */ + afterHero?: React.ReactNode; + /* Home 页 Features 部分之前 */ + beforeFeatures?: React.ReactNode; + /* Home 页 Features 部分之后 */ + afterFeatures?: React.ReactNode; + /* 正文页 Footer 部分之前 */ + beforeDocFooter?: React.ReactNode; + /* 正文页最前面 */ + beforeDoc?: React.ReactNode; + /* 正文页最后面 */ + afterDoc?: React.ReactNode; + /* 左上角导航栏标题之前 */ + beforeNavTitle?: React.ReactNode; + /* 左上角导航栏标题之后 */ + afterNavTitle?: React.ReactNode; + /* 右侧大纲栏上面 */ + beforeOutline?: React.ReactNode; + /* 右侧大纲栏下面 */ + afterOutline?: React.ReactNode; + /* 整个页面最顶部 */ + top?: React.ReactNode; + /* 整个页面最底部 */ + bottom?: React.ReactNode; +} +``` + +## HomeLayout + +`HomeLayout` 组件是主题的 Home 页布局组件,它会被 Island.js 用来渲染 Home 页的布局。 + +```tsx +// theme/index.tsx +import { HomeLayout } from 'islandjs'; +``` + +## NotFoundLayout + +`NotFoundLayout` 组件是主题的 404 页面布局组件,它会被 Island.js 用来渲染 404 页面的布局。 + +## setup + +`setup` 用来添加一个初始化的逻辑,比如全局事件绑定。 + +```tsx +// theme/index.tsx +import { setup } from 'islandjs'; +``` diff --git a/docs/zh/api/config-theme.mdx b/docs/zh/api/config-theme.mdx index 5b0d9cee..cffcbed2 100644 --- a/docs/zh/api/config-theme.mdx +++ b/docs/zh/api/config-theme.mdx @@ -1,6 +1,6 @@ # 主题配置 -import Locales from '../fragments/locales.md'; +import Locales from '../fragments/locales.mdx'; 主题配置位于根配置中的 `themeConfig` 下。例如: diff --git a/docs/zh/fragments/content.mdx b/docs/zh/fragments/content.mdx new file mode 100644 index 00000000..b15e2341 --- /dev/null +++ b/docs/zh/fragments/content.mdx @@ -0,0 +1,13 @@ +获取正文 MDX 组件内容,即正文内容: + +```ts +import { Content } from 'islandjs/runtime'; + +function Layout() { + return ( +
+ +
+ ); +} +``` diff --git a/docs/zh/fragments/locales.md b/docs/zh/fragments/locales.mdx similarity index 100% rename from docs/zh/fragments/locales.md rename to docs/zh/fragments/locales.mdx diff --git a/docs/zh/fragments/route-hook.mdx b/docs/zh/fragments/route-hook.mdx new file mode 100644 index 00000000..dbe63241 --- /dev/null +++ b/docs/zh/fragments/route-hook.mdx @@ -0,0 +1,10 @@ +Island.js 内部用 [react-router-dom](https://reactrouter.com/) 来实现路由,所以你可以直接使用 `react-router-dom` 的 Hook,比如: + +```ts +import { useLocation } from 'islandjs/runtime'; + +function Layout() { + const location = useLocation(); + return
Current location: {location.pathname}
; +} +``` diff --git a/docs/zh/fragments/use-page-data.mdx b/docs/zh/fragments/use-page-data.mdx new file mode 100644 index 00000000..bad96bc8 --- /dev/null +++ b/docs/zh/fragments/use-page-data.mdx @@ -0,0 +1,45 @@ +用户获取页面所有数据的 Hook,比如: + +```tsx +import { usePageData } from 'islandjs/runtime'; + +function Layout() { + const pageData = usePageData(); + return
{pageData.title}
; +} +``` + +`usePageData` 类型如下: + +```ts +const usePageData: () => PageData; +``` + +`PageData` 的类型如下: + +```ts +export interface PageData { + // 站点通用信息,包含主题配置 themeConfig 信息 + siteData: SiteData; + // 上次更新时间 + lastUpdatedTime?: string; + // 页面标题 + title?: string; + // 页面描述 + description?: string; + // Front Matter 元数据 + frontmatter?: FrontMatterMeta; + // 页面类型 + pageType: PageType; + // TOC 数据,包含标题和对应的锚点 + toc?: Header[]; + // 当前路由路径 + routePath: string; + // 页面的路径,去掉 query 和 hash + pagePath: string; + // 页面的正文内容 + content?: string; +} +``` + +基于此 API,你基本可以获取到需要的所有数据。 diff --git a/docs/zh/guide/custom-theme.md b/docs/zh/guide/custom-theme.md deleted file mode 100644 index 17f107ab..00000000 --- a/docs/zh/guide/custom-theme.md +++ /dev/null @@ -1,3 +0,0 @@ -# 自定义主题 - -🚧 敬请期待。 diff --git a/docs/zh/guide/custom-theme.mdx b/docs/zh/guide/custom-theme.mdx new file mode 100644 index 00000000..62329e98 --- /dev/null +++ b/docs/zh/guide/custom-theme.mdx @@ -0,0 +1,190 @@ +# 自定义主题 + +import UsePageData from '../fragments/use-page-data.mdx'; +import Content from '../fragments/content.mdx'; +import RouteHook from '../fragments/route-hook.mdx'; + +Island.js 内置一套开箱即用的默认主题,且内部的组件也提供了配置来自定义,包括: + +- [导航栏](/zh/guide/navbar) +- [Home 主页](/zh/guide/home-page) +- [API 预览页](/zh/guide/api-page) +- [正文页面](/zh/guide/doc-page) +- [国际化模块](/zh/guide/i18n) +- [全文搜索模块](/zh/guide/search) + +你可以点进对应的页面查看具体的配置项。本文所要介绍的是如何开发一个自定义主题。 + +## 基于默认主题的扩展 + +大部分情况下,你并不想从零开始开发一个主题,而是想基于默认主题进行扩展,这时候可以参考下面的方式进行主题开发。 + +:::tip +如果你想从头开发一个自定义主题,可以前往[【重新开发自定义主题】](/zh/guide/custom-theme#重新开发自定义主题)。 +::: + +### 1. 基本结构 + +默认情况下,你需要在 `.island` 目录下创建一个 `theme` 目录,然后在这个目录下创建一个 `index.ts(x)` 文件,这个文件就是你的主题入口文件: + +```bash +.island +├── config.ts +└── theme + └── index.tsx +``` + +你可以使用如下的方式来书写 `theme/index.tsx` 文件: + +```ts +// `theme/index.tsx` +import React from 'react'; +import { + Layout as DefaultLayout, + NotFoundLayout, + HomeLayout, + setup +} from 'islandjs/theme'; +// 添加一些自定义的样式 +import './custom.css'; + +const Layout = () => beforeHero} />; + +// 导出三个组件和 setup 函数 +export { Layout, HomeLayout, NotFoundLayout, setup }; +``` + +可以看到,你能从`islandjs/theme`中获取并导出默认主题的各个组件,包括: + +- **Layout 组件**,页面的布局组件 +- **HomeLayout 组件**,首页的布局组件,被 Layout 组件使用 +- **NotFoundLayout 组件**,404 页面的布局组件,被 Layout 组件使用 +- 还包括 **setup 函数**,用来添加一个初始化的逻辑,比如全局事件绑定,必须导出 + +### 2. 使用插槽 + +值得注意的是,Layout 组件设计了一系列的 props 支持插槽元素,你可以通过这些 props 来扩展默认主题的布局,比如将上面的 Layout 组件改成如下的形式: + +```tsx +import { Layout as DefaultLayout } from 'islandjs/theme'; + +// 以下展示所有的 Props +const Layout = () => ( + beforeHero} + /* Home 页 Hero 部分之后 */ + afterHero={
afterHero
} + /* Home 页 Features 部分之前 */ + beforeFeatures={
beforeFeatures
} + /* Home 页 Features 部分之后 */ + afterFeatures={
afterFeatures
} + /* 正文页 Footer 部分之前 */ + beforeDocFooter={
beforeDocFooter
} + /* 正文页最前面 */ + beforeDoc={
beforeDoc
} + /* 正文页最后面 */ + afterDoc={
afterDoc
} + /* 左上角导航栏标题之前 */ + beforeNavTitle={😄} + /* 左上角导航栏标题之后 */ + afterNavTitle={
afterNavTitle
} + /* 右侧大纲栏上面 */ + beforeOutline={
beforeOutline
} + /* 右侧大纲栏下面 */ + afterOutline={
afterOutline
} + /* 整个页面最顶部 */ + top={
top
} + /* 整个页面最底部 */ + bottom={
bottom
} + /> +); +``` + +### 3. 自定义组件 + +要扩展默认主题的组件,除了插槽,你还可以自定义 Home 页面及 404 页面组件,比如: + +```tsx +import { Layout, setup } from 'islandjs/theme'; +// 定制 Home 页面 +const HomeLayout = () =>
Home
; +// 定制 404 页面 +const NotFoundLayout = () =>
404
; + +export { Layout, HomeLayout, NotFoundLayout, setup }; +``` + +当然,在开发过程可能需要使用页面的数据,你可以通过 [`usePageData`](/zh/guide/custom-theme#usepagedata) 这个 Hook 来获取。 + +## 重新开发自定义主题 + +### 1. 基本结构 + +当然,如果你要从头开始开发一个自定义主题,你需要了解一下主题的组成。 + +默认情况下,你需要在 `.island` 目录下创建一个 `theme` 目录,然后在这个目录下创建一个 `index.ts(x)` 文件,这个文件就是你的主题入口文件: + +```bash +.island +├── config.ts +└── theme + └── index.tsx +``` + +在`theme/index.tsx`文件中,你需要导出一个 Layout 组件,这个组件就是你的主题的入口组件: + +```ts +// theme/index.tsx +function Layout() { + return
Custom Theme Layout
; +} + +// setup 函数,会在页面初始化时调用,一般用来做全局事件的监听,可为空函数 +const setup = () => {}; + +// 导出 Layout 组件和 setup 函数 +// 两者必须导出 +export { Layout, setup }; +``` + +这个 Layout 组件会被 Island.js 用来渲染整个文档站点的布局,你可以在这个组件中引入你的自定义组件,比如: + +```ts +// theme/index.tsx +import { Navbar } from './Navbar'; + +function Layout() { + return ( +
+ +
Custom Theme Layout
+
+ ); +} + +export { Layout }; + +// theme/Navbar.tsx +export function Navbar() { + return
Custom Navbar
; +} +``` + +那么问题来了,主题组件是如何获取页面数据和正文 MDX 组件内容的呢?这就需要用到 Island.js 的 `Runtime API` 了。 + +### 2. 接入 Runtime API + +在主题开发的过程中,我们一般需要如下的一些关键 API: + +#### usePageData + + + +#### Content + + + +#### 路由 Hook + + diff --git a/docs/zh/guide/i18n.mdx b/docs/zh/guide/i18n.mdx index 512931a1..9f87740a 100644 --- a/docs/zh/guide/i18n.mdx +++ b/docs/zh/guide/i18n.mdx @@ -1,6 +1,6 @@ # 国际化 -import Locales from '../fragments/locales.md'; +import Locales from '../fragments/locales.mdx'; Island.js 提供了一套简单可配置的国际化方案,接下来我们将介绍如何在你的项目中接入。 diff --git a/package.json b/package.json index 21439a1f..9e2e0e7d 100644 --- a/package.json +++ b/package.json @@ -161,7 +161,9 @@ "vendors", "template.html", "src/shared/constants", - "src/shared/utils" + "src/shared/utils", + "runtime.d.ts", + "theme.d.ts" ], "lint-staged": { "**/*.{js,jsx,tsx,ts,json}": [ diff --git a/src/runtime/index.ts b/src/runtime/index.ts index eeecfa89..1b50d424 100644 --- a/src/runtime/index.ts +++ b/src/runtime/index.ts @@ -1,2 +1,3 @@ export { Content } from './Content'; export { usePageData, DataContext, getAllPages } from './hooks'; +export * from 'react-router-dom'; diff --git a/src/theme-default/components/Aside/index.tsx b/src/theme-default/components/Aside/index.tsx index 6cb1e7c9..bd050d43 100644 --- a/src/theme-default/components/Aside/index.tsx +++ b/src/theme-default/components/Aside/index.tsx @@ -49,9 +49,8 @@ export function Aside( }, [props.pagePath]); const renderHeader = (header: Header) => { - const isNested = header.depth > 2; return ( -
  • +
  • {header.text} diff --git a/src/theme-default/layout/DocLayout/index.tsx b/src/theme-default/layout/DocLayout/index.tsx index 2f3aa702..2b8963d7 100644 --- a/src/theme-default/layout/DocLayout/index.tsx +++ b/src/theme-default/layout/DocLayout/index.tsx @@ -4,6 +4,7 @@ import { Aside } from '../../components/Aside/index'; import { DocFooter } from '../../components/DocFooter/index'; import { Content, usePageData } from '@client'; import { useLocaleSiteData } from '../../logic'; +import { useEffect, useRef } from 'react'; export interface DocLayoutProps { beforeDocFooter?: React.ReactNode; @@ -32,8 +33,23 @@ export function DocLayout(props: DocLayoutProps) { localesData?.outlineTitle || themeConfig?.outlineTitle || 'ON THIS PAGE'; const hasAside = headers.length > 0 && - themeConfig.outline !== false && - frontmatter?.outline !== false; + (frontmatter?.outline ?? themeConfig?.outline ?? true); + const scrollYRef = useRef(0); + + if (scrollYRef.current) { + window.scrollTo(0, scrollYRef.current); + } + + useEffect(() => { + const onScroll = () => { + scrollYRef.current = window.scrollY; + console.log('scrollYRef', scrollYRef.current); + }; + window.addEventListener('scroll', onScroll); + return () => { + window.removeEventListener('scroll', onScroll); + }; + }, []); return (
    diff --git a/src/theme-default/layout/Layout/index.tsx b/src/theme-default/layout/Layout/index.tsx index 7ea6b7b2..d7d76dbe 100644 --- a/src/theme-default/layout/Layout/index.tsx +++ b/src/theme-default/layout/Layout/index.tsx @@ -16,7 +16,7 @@ export type LayoutProps = { HomeLayoutProps & NavProps; -export const Layout: React.FC = (props: LayoutProps) => { +export const Layout: React.FC = (props) => { const { top, bottom,