@modern-js/main-doc 2.33.0 → 2.34.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/configure/app/server/ssr.mdx +2 -0
- package/docs/en/tutorials/examples/_category_.json +5 -0
- package/docs/en/tutorials/examples/csr-auth.mdx +214 -0
- package/docs/en/tutorials/foundations/introduction.mdx +10 -1
- package/docs/zh/configure/app/server/ssr.mdx +3 -0
- package/docs/zh/guides/basic-features/routes.mdx +1 -1
- package/docs/zh/tutorials/examples/_category_.json +5 -0
- package/docs/zh/tutorials/examples/csr-auth.mdx +214 -0
- package/docs/zh/tutorials/foundations/introduction.mdx +8 -0
- package/package.json +7 -4
- package/src/components/Sandpack/index.css +10 -0
- package/src/components/Sandpack/index.tsx +30 -0
- package/CHANGELOG.md +0 -425
@@ -28,6 +28,8 @@ When the value type is `Object`, the following properties can be configured:
|
|
28
28
|
- `mode`: `string = 'string'`, which defaults to using `renderToString` for rendering. Configure `stream` to enable streaming rendering.
|
29
29
|
- `forceCSR`: `boolean = false`, which is off by default for forcing CSR rendering. Configure `true` to force CSR by adding `?csr=true` or adding `x-modern-ssr-fallback` header when accessing the page.
|
30
30
|
- `inlineScript`: `boolean = true`, by default, SSR data is injected into HTML as inline scripts and assigned directly to global variables. Configure `false` to distribute JSON instead of assigning to global variables.
|
31
|
+
- `disablePrerender`: `boolean = fasle`, To ensure compatibility with the old data request method (`useLoader`), by default, Modern.js performs pre-rendering of components.
|
32
|
+
However, if developers want to reduce one rendering when there is no use of the useLoader API in your project, you can set the configuration `disablePrerender=true`.
|
31
33
|
|
32
34
|
```ts title="modern.config.ts"
|
33
35
|
export default defineConfig({
|
@@ -0,0 +1,214 @@
|
|
1
|
+
---
|
2
|
+
title: Route Authorization
|
3
|
+
---
|
4
|
+
|
5
|
+
# Route Authorization
|
6
|
+
|
7
|
+
Modern.js defaults to the convention-based routing based on React Router 6. For more details, please refer to [Routing](/guides/basic-features/routes.html#routing-scheme).
|
8
|
+
|
9
|
+
In a web application, if there are multiple routes, we may need to authorize access to some of them before accessing them. For example, in the following scenario:
|
10
|
+
|
11
|
+
- Access to the `/` route does not require authorization and can be accessed directly.
|
12
|
+
- Access to the `/protected` route requires authorization. If there is no authorization, it will automatically redirect to the `/login` route. After successful login, it returns to `/protected`.
|
13
|
+
|
14
|
+
import Sandpack from '@site/src/components/Sandpack';
|
15
|
+
|
16
|
+
<Sandpack template="web-app">
|
17
|
+
```tsx title="src/routes/page.tsx"
|
18
|
+
import { Helmet } from '@modern-js/runtime/head';
|
19
|
+
import './index.css';
|
20
|
+
|
21
|
+
const PublicPage = (): JSX.Element => (
|
22
|
+
<div className="container-box">
|
23
|
+
<Helmet>
|
24
|
+
<link
|
25
|
+
rel="icon"
|
26
|
+
type="image/x-icon"
|
27
|
+
href="https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/favicon.ico"
|
28
|
+
/>
|
29
|
+
</Helmet>
|
30
|
+
<h3>Public</h3>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
|
34
|
+
export default PublicPage;
|
35
|
+
|
36
|
+
```
|
37
|
+
```tsx title="src/routes/layout.tsx"
|
38
|
+
import { Link, Outlet } from '@modern-js/runtime/router';
|
39
|
+
import { AuthProvider, AuthStatus } from './Auth';
|
40
|
+
|
41
|
+
export default function Layout() {
|
42
|
+
return (
|
43
|
+
<AuthProvider>
|
44
|
+
<AuthStatus />
|
45
|
+
|
46
|
+
<ul>
|
47
|
+
<li>
|
48
|
+
<Link to="/">Public Page</Link>
|
49
|
+
</li>
|
50
|
+
<li>
|
51
|
+
<Link to="/protected">Protected Page</Link>
|
52
|
+
</li>
|
53
|
+
</ul>
|
54
|
+
|
55
|
+
<Outlet />
|
56
|
+
</AuthProvider>
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
```
|
61
|
+
```ts title="src/routes/fakeAuth.ts"
|
62
|
+
/**
|
63
|
+
* This represents some generic auth provider API, like Firebase.
|
64
|
+
*/
|
65
|
+
const fakeAuthProvider = {
|
66
|
+
isAuthenticated: false,
|
67
|
+
signin(callback: VoidFunction) {
|
68
|
+
fakeAuthProvider.isAuthenticated = true;
|
69
|
+
setTimeout(callback, 100); // fake async
|
70
|
+
},
|
71
|
+
signout(callback: VoidFunction) {
|
72
|
+
fakeAuthProvider.isAuthenticated = false;
|
73
|
+
setTimeout(callback, 100);
|
74
|
+
},
|
75
|
+
};
|
76
|
+
|
77
|
+
export { fakeAuthProvider };
|
78
|
+
|
79
|
+
```
|
80
|
+
```ts title="src/routes/Auth.tsx"
|
81
|
+
import React from 'react';
|
82
|
+
import { useNavigate, Navigate, useLocation } from '@modern-js/runtime/router';
|
83
|
+
import { fakeAuthProvider } from './fakeAuth';
|
84
|
+
|
85
|
+
interface AuthContextType {
|
86
|
+
user: any;
|
87
|
+
signin: (user: string, callback: VoidFunction) => void;
|
88
|
+
signout: (callback: VoidFunction) => void;
|
89
|
+
}
|
90
|
+
|
91
|
+
const AuthContext = React.createContext<AuthContextType>(null!);
|
92
|
+
|
93
|
+
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
94
|
+
const [user, setUser] = React.useState<any>(null);
|
95
|
+
|
96
|
+
const signin = (newUser: string, callback: VoidFunction) =>
|
97
|
+
fakeAuthProvider.signin(() => {
|
98
|
+
setUser(newUser);
|
99
|
+
callback();
|
100
|
+
});
|
101
|
+
|
102
|
+
const signout = (callback: VoidFunction) =>
|
103
|
+
fakeAuthProvider.signout(() => {
|
104
|
+
setUser(null);
|
105
|
+
callback();
|
106
|
+
});
|
107
|
+
|
108
|
+
const value = { user, signin, signout };
|
109
|
+
|
110
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
111
|
+
}
|
112
|
+
|
113
|
+
export function useAuth() {
|
114
|
+
return React.useContext(AuthContext);
|
115
|
+
}
|
116
|
+
|
117
|
+
export function AuthStatus() {
|
118
|
+
const auth = useAuth();
|
119
|
+
console.log('auth', auth);
|
120
|
+
const navigate = useNavigate();
|
121
|
+
|
122
|
+
if (!auth.user) {
|
123
|
+
return <p>You are not logged in.</p>;
|
124
|
+
}
|
125
|
+
|
126
|
+
return (
|
127
|
+
<p>
|
128
|
+
Welcome {auth.user}!{' '}
|
129
|
+
<button
|
130
|
+
type="button"
|
131
|
+
onClick={() => {
|
132
|
+
auth.signout(() => navigate('/'));
|
133
|
+
}}
|
134
|
+
>
|
135
|
+
Sign out
|
136
|
+
</button>
|
137
|
+
</p>
|
138
|
+
);
|
139
|
+
}
|
140
|
+
|
141
|
+
export function RequireAuth({ children }: { children: JSX.Element }) {
|
142
|
+
const auth = useAuth();
|
143
|
+
const location = useLocation();
|
144
|
+
|
145
|
+
if (!auth.user) {
|
146
|
+
// Redirect them to the /login page, but save the current location they were
|
147
|
+
// trying to go to when they were redirected. This allows us to send them
|
148
|
+
// along to that page after they login, which is a nicer user experience
|
149
|
+
// than dropping them off on the home page.
|
150
|
+
return <Navigate to="/login" state={{ from: location }} replace />;
|
151
|
+
}
|
152
|
+
|
153
|
+
return children;
|
154
|
+
}
|
155
|
+
|
156
|
+
```
|
157
|
+
```ts title="src/routes/protected/page.tsx"
|
158
|
+
import { RequireAuth } from '../Auth';
|
159
|
+
|
160
|
+
export default function ProtectedPage() {
|
161
|
+
return (
|
162
|
+
<div className="container-box">
|
163
|
+
<RequireAuth>
|
164
|
+
<h3>Protected</h3>
|
165
|
+
</RequireAuth>
|
166
|
+
</div>
|
167
|
+
);
|
168
|
+
}
|
169
|
+
|
170
|
+
```
|
171
|
+
```ts title="src/routes/login/page.tsx"
|
172
|
+
import { useLocation, useNavigate } from '@modern-js/runtime/router';
|
173
|
+
import { useAuth } from '../Auth';
|
174
|
+
|
175
|
+
export default function Login() {
|
176
|
+
const navigate = useNavigate();
|
177
|
+
const location = useLocation();
|
178
|
+
const auth = useAuth();
|
179
|
+
|
180
|
+
const from = location.state?.from?.pathname || '/';
|
181
|
+
|
182
|
+
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
|
183
|
+
event.preventDefault();
|
184
|
+
|
185
|
+
const formData = new FormData(event.currentTarget);
|
186
|
+
const username = formData.get('username') as string;
|
187
|
+
|
188
|
+
auth.signin(username, () => {
|
189
|
+
// Send them back to the page they tried to visit when they were
|
190
|
+
// redirected to the login page. Use { replace: true } so we don't create
|
191
|
+
// another entry in the history stack for the login page. This means that
|
192
|
+
// when they get to the protected page and click the back button, they
|
193
|
+
// won't end up back on the login page, which is also really nice for the
|
194
|
+
// user experience.
|
195
|
+
navigate(from, { replace: true });
|
196
|
+
});
|
197
|
+
}
|
198
|
+
|
199
|
+
return (
|
200
|
+
<div>
|
201
|
+
<p>You must log in to view the page at {from}</p>
|
202
|
+
|
203
|
+
<form onSubmit={handleSubmit}>
|
204
|
+
<label>
|
205
|
+
Username: <input name="username" type="text" />
|
206
|
+
</label>{' '}
|
207
|
+
<button type="submit">Login</button>
|
208
|
+
</form>
|
209
|
+
</div>
|
210
|
+
);
|
211
|
+
}
|
212
|
+
|
213
|
+
```
|
214
|
+
</Sandpack>
|
@@ -24,5 +24,14 @@ We have prepared a tutorial on creating a "contact list app" that you can follow
|
|
24
24
|
- Data fetching
|
25
25
|
- State Management
|
26
26
|
- Container components
|
27
|
-
- New
|
27
|
+
- New entry
|
28
28
|
- ...
|
29
|
+
|
30
|
+
## Case Studies
|
31
|
+
|
32
|
+
We offer some commonly used case studies for your reference during the development process. Here you can find some usage patterns of the feature combinations provided by Modern.js. We will continue to improve the case studies here.
|
33
|
+
|
34
|
+
- [Route Authorization](/tutorials/examples/csr-auth.html)
|
35
|
+
- ...
|
36
|
+
|
37
|
+
Let's start from [creating a project](tutorials/first-app/c01-start) now!
|
@@ -28,6 +28,8 @@ export default defineConfig({
|
|
28
28
|
- `mode`:`string = 'string'`,默认为使用 `renderToString` 渲染。配置为 `stream` 开启流式渲染。
|
29
29
|
- `forceCSR`:`boolean = false`,默认关闭强制 CSR 渲染。配置为 `true` 后,在页面访问时添加 `?csr=true` 或添加请求头 `x-modern-ssr-fallback` 即可强制 CSR。
|
30
30
|
- `inlineScript`:`boolean = true`,默认情况下,SSR 的数据会以内联脚本的方式注入到 HTML 中,并且直接赋值给全局变量。配置为 `false` 后,会下发 JSON,而不是赋值给全局变量。
|
31
|
+
- `disablePrerender`: `boolean = fasle`, 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染。
|
32
|
+
开发者在保证项目中没有使用 useLoader Api 情况下, 可通过配置 `disablePrerender=true`来减少一次渲染。
|
31
33
|
|
32
34
|
```ts title="modern.config.ts"
|
33
35
|
export default defineConfig({
|
@@ -36,6 +38,7 @@ export default defineConfig({
|
|
36
38
|
forceCSR: true,
|
37
39
|
mode: 'stream',
|
38
40
|
inlineScript: false,
|
41
|
+
disablePrerender: true,
|
39
42
|
},
|
40
43
|
},
|
41
44
|
});
|
@@ -207,7 +207,7 @@ export default () => {
|
|
207
207
|
└── page.tsx
|
208
208
|
```
|
209
209
|
|
210
|
-
`routes/user/[id$]/page.tsx` 文件会转为 `/user/:id?` 路由。`/user` 下的所有路由都会匹配到该路由,并且 `id`
|
210
|
+
`routes/user/[id$]/page.tsx` 文件会转为 `/user/:id?` 路由。`/user` 下的所有路由都会匹配到该路由,并且 `id` 参数可选存在。通常在区分**创建**与**编辑**时,可以使用该路由。
|
211
211
|
|
212
212
|
在组件中,可以通过 [useParams](/apis/app/runtime/router/router#useparams) 获取对应命名的参数。
|
213
213
|
|
@@ -0,0 +1,214 @@
|
|
1
|
+
---
|
2
|
+
title: 路由鉴权
|
3
|
+
---
|
4
|
+
|
5
|
+
# 路由鉴权
|
6
|
+
|
7
|
+
Modern.js 默认提供的路由方式是基于 React Router 6 的约定式路由,具体可查看[路由方案](/guides/basic-features/routes.html#路由方案)。
|
8
|
+
|
9
|
+
在一个 Web 应用中如果存在多个路由,我们可能需要对部分路由进行鉴权后才能访问。例如下面这个案例:
|
10
|
+
|
11
|
+
- 访问 `/` 路由,无需鉴权,可直接访问。
|
12
|
+
- 访问 `/protected` 路由,需要鉴权,如果无,自动跳转到 `/login` 路由,登录成功后返回 `/protected`。
|
13
|
+
|
14
|
+
import Sandpack from '@site/src/components/Sandpack';
|
15
|
+
|
16
|
+
<Sandpack template="web-app">
|
17
|
+
```tsx title="src/routes/page.tsx"
|
18
|
+
import { Helmet } from '@modern-js/runtime/head';
|
19
|
+
import './index.css';
|
20
|
+
|
21
|
+
const PublicPage = (): JSX.Element => (
|
22
|
+
<div className="container-box">
|
23
|
+
<Helmet>
|
24
|
+
<link
|
25
|
+
rel="icon"
|
26
|
+
type="image/x-icon"
|
27
|
+
href="https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/favicon.ico"
|
28
|
+
/>
|
29
|
+
</Helmet>
|
30
|
+
<h3>Public</h3>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
|
34
|
+
export default PublicPage;
|
35
|
+
|
36
|
+
```
|
37
|
+
```tsx title="src/routes/layout.tsx"
|
38
|
+
import { Link, Outlet } from '@modern-js/runtime/router';
|
39
|
+
import { AuthProvider, AuthStatus } from './Auth';
|
40
|
+
|
41
|
+
export default function Layout() {
|
42
|
+
return (
|
43
|
+
<AuthProvider>
|
44
|
+
<AuthStatus />
|
45
|
+
|
46
|
+
<ul>
|
47
|
+
<li>
|
48
|
+
<Link to="/">Public Page</Link>
|
49
|
+
</li>
|
50
|
+
<li>
|
51
|
+
<Link to="/protected">Protected Page</Link>
|
52
|
+
</li>
|
53
|
+
</ul>
|
54
|
+
|
55
|
+
<Outlet />
|
56
|
+
</AuthProvider>
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
```
|
61
|
+
```ts title="src/routes/fakeAuth.ts"
|
62
|
+
/**
|
63
|
+
* This represents some generic auth provider API, like Firebase.
|
64
|
+
*/
|
65
|
+
const fakeAuthProvider = {
|
66
|
+
isAuthenticated: false,
|
67
|
+
signin(callback: VoidFunction) {
|
68
|
+
fakeAuthProvider.isAuthenticated = true;
|
69
|
+
setTimeout(callback, 100); // fake async
|
70
|
+
},
|
71
|
+
signout(callback: VoidFunction) {
|
72
|
+
fakeAuthProvider.isAuthenticated = false;
|
73
|
+
setTimeout(callback, 100);
|
74
|
+
},
|
75
|
+
};
|
76
|
+
|
77
|
+
export { fakeAuthProvider };
|
78
|
+
|
79
|
+
```
|
80
|
+
```ts title="src/routes/Auth.tsx"
|
81
|
+
import React from 'react';
|
82
|
+
import { useNavigate, Navigate, useLocation } from '@modern-js/runtime/router';
|
83
|
+
import { fakeAuthProvider } from './fakeAuth';
|
84
|
+
|
85
|
+
interface AuthContextType {
|
86
|
+
user: any;
|
87
|
+
signin: (user: string, callback: VoidFunction) => void;
|
88
|
+
signout: (callback: VoidFunction) => void;
|
89
|
+
}
|
90
|
+
|
91
|
+
const AuthContext = React.createContext<AuthContextType>(null!);
|
92
|
+
|
93
|
+
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
94
|
+
const [user, setUser] = React.useState<any>(null);
|
95
|
+
|
96
|
+
const signin = (newUser: string, callback: VoidFunction) =>
|
97
|
+
fakeAuthProvider.signin(() => {
|
98
|
+
setUser(newUser);
|
99
|
+
callback();
|
100
|
+
});
|
101
|
+
|
102
|
+
const signout = (callback: VoidFunction) =>
|
103
|
+
fakeAuthProvider.signout(() => {
|
104
|
+
setUser(null);
|
105
|
+
callback();
|
106
|
+
});
|
107
|
+
|
108
|
+
const value = { user, signin, signout };
|
109
|
+
|
110
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
111
|
+
}
|
112
|
+
|
113
|
+
export function useAuth() {
|
114
|
+
return React.useContext(AuthContext);
|
115
|
+
}
|
116
|
+
|
117
|
+
export function AuthStatus() {
|
118
|
+
const auth = useAuth();
|
119
|
+
console.log('auth', auth);
|
120
|
+
const navigate = useNavigate();
|
121
|
+
|
122
|
+
if (!auth.user) {
|
123
|
+
return <p>You are not logged in.</p>;
|
124
|
+
}
|
125
|
+
|
126
|
+
return (
|
127
|
+
<p>
|
128
|
+
Welcome {auth.user}!{' '}
|
129
|
+
<button
|
130
|
+
type="button"
|
131
|
+
onClick={() => {
|
132
|
+
auth.signout(() => navigate('/'));
|
133
|
+
}}
|
134
|
+
>
|
135
|
+
Sign out
|
136
|
+
</button>
|
137
|
+
</p>
|
138
|
+
);
|
139
|
+
}
|
140
|
+
|
141
|
+
export function RequireAuth({ children }: { children: JSX.Element }) {
|
142
|
+
const auth = useAuth();
|
143
|
+
const location = useLocation();
|
144
|
+
|
145
|
+
if (!auth.user) {
|
146
|
+
// Redirect them to the /login page, but save the current location they were
|
147
|
+
// trying to go to when they were redirected. This allows us to send them
|
148
|
+
// along to that page after they login, which is a nicer user experience
|
149
|
+
// than dropping them off on the home page.
|
150
|
+
return <Navigate to="/login" state={{ from: location }} replace />;
|
151
|
+
}
|
152
|
+
|
153
|
+
return children;
|
154
|
+
}
|
155
|
+
|
156
|
+
```
|
157
|
+
```ts title="src/routes/protected/page.tsx"
|
158
|
+
import { RequireAuth } from '../Auth';
|
159
|
+
|
160
|
+
export default function ProtectedPage() {
|
161
|
+
return (
|
162
|
+
<div className="container-box">
|
163
|
+
<RequireAuth>
|
164
|
+
<h3>Protected</h3>
|
165
|
+
</RequireAuth>
|
166
|
+
</div>
|
167
|
+
);
|
168
|
+
}
|
169
|
+
|
170
|
+
```
|
171
|
+
```ts title="src/routes/login/page.tsx"
|
172
|
+
import { useLocation, useNavigate } from '@modern-js/runtime/router';
|
173
|
+
import { useAuth } from '../Auth';
|
174
|
+
|
175
|
+
export default function Login() {
|
176
|
+
const navigate = useNavigate();
|
177
|
+
const location = useLocation();
|
178
|
+
const auth = useAuth();
|
179
|
+
|
180
|
+
const from = location.state?.from?.pathname || '/';
|
181
|
+
|
182
|
+
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
|
183
|
+
event.preventDefault();
|
184
|
+
|
185
|
+
const formData = new FormData(event.currentTarget);
|
186
|
+
const username = formData.get('username') as string;
|
187
|
+
|
188
|
+
auth.signin(username, () => {
|
189
|
+
// Send them back to the page they tried to visit when they were
|
190
|
+
// redirected to the login page. Use { replace: true } so we don't create
|
191
|
+
// another entry in the history stack for the login page. This means that
|
192
|
+
// when they get to the protected page and click the back button, they
|
193
|
+
// won't end up back on the login page, which is also really nice for the
|
194
|
+
// user experience.
|
195
|
+
navigate(from, { replace: true });
|
196
|
+
});
|
197
|
+
}
|
198
|
+
|
199
|
+
return (
|
200
|
+
<div>
|
201
|
+
<p>You must log in to view the page at {from}</p>
|
202
|
+
|
203
|
+
<form onSubmit={handleSubmit}>
|
204
|
+
<label>
|
205
|
+
Username: <input name="username" type="text" />
|
206
|
+
</label>{' '}
|
207
|
+
<button type="submit">Login</button>
|
208
|
+
</form>
|
209
|
+
</div>
|
210
|
+
);
|
211
|
+
}
|
212
|
+
|
213
|
+
```
|
214
|
+
</Sandpack>
|
package/package.json
CHANGED
@@ -15,14 +15,17 @@
|
|
15
15
|
"modern",
|
16
16
|
"modern.js"
|
17
17
|
],
|
18
|
-
"version": "2.
|
18
|
+
"version": "2.34.0",
|
19
19
|
"publishConfig": {
|
20
20
|
"registry": "https://registry.npmjs.org/",
|
21
21
|
"access": "public",
|
22
22
|
"provenance": true
|
23
23
|
},
|
24
|
+
"dependencies": {
|
25
|
+
"@modern-js/sandpack-react": "2.34.0"
|
26
|
+
},
|
24
27
|
"peerDependencies": {
|
25
|
-
"@modern-js/builder-doc": "^2.
|
28
|
+
"@modern-js/builder-doc": "^2.34.0"
|
26
29
|
},
|
27
30
|
"devDependencies": {
|
28
31
|
"classnames": "^2",
|
@@ -36,8 +39,8 @@
|
|
36
39
|
"@rspress/shared": "0.0.6",
|
37
40
|
"@types/node": "^16",
|
38
41
|
"@types/fs-extra": "^9",
|
39
|
-
"@modern-js/doc
|
40
|
-
"@modern-js/
|
42
|
+
"@modern-js/builder-doc": "2.34.0",
|
43
|
+
"@modern-js/doc-plugin-auto-sidebar": "2.34.0"
|
41
44
|
},
|
42
45
|
"scripts": {
|
43
46
|
"dev": "rspress dev",
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import ModernSandpack, { ModernSandpackProps } from '@modern-js/sandpack-react';
|
2
|
+
import React, { PropsWithChildren } from 'react';
|
3
|
+
import { useDark, NoSSR } from 'rspress/runtime';
|
4
|
+
|
5
|
+
import './index.css';
|
6
|
+
|
7
|
+
const Sandpack = (props: PropsWithChildren<ModernSandpackProps>) => {
|
8
|
+
const dark = useDark();
|
9
|
+
const { children, ...otherProps } = props;
|
10
|
+
const files: Record<string, string> = {};
|
11
|
+
React.Children.forEach(children, (child: any) => {
|
12
|
+
if (child) {
|
13
|
+
const { meta, children } = child.props.children.props;
|
14
|
+
const matches = meta.match(/title="(.*)"/);
|
15
|
+
if (matches.length > 1) {
|
16
|
+
files[matches[1]] = children;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
});
|
20
|
+
return (
|
21
|
+
<NoSSR>
|
22
|
+
<ModernSandpack
|
23
|
+
files={files}
|
24
|
+
theme={dark ? 'dark' : 'light'}
|
25
|
+
{...otherProps}
|
26
|
+
/>
|
27
|
+
</NoSSR>
|
28
|
+
);
|
29
|
+
};
|
30
|
+
export default Sandpack;
|
package/CHANGELOG.md
DELETED
@@ -1,425 +0,0 @@
|
|
1
|
-
# @modern-js/main-doc
|
2
|
-
|
3
|
-
## 2.33.0
|
4
|
-
|
5
|
-
### Patch Changes
|
6
|
-
|
7
|
-
- bc1f8da: feat(builder): support custom logger in dev server
|
8
|
-
|
9
|
-
feat(builder): 支持自定义 logger
|
10
|
-
|
11
|
-
- @modern-js/builder-doc@2.33.0
|
12
|
-
|
13
|
-
## 2.32.1
|
14
|
-
|
15
|
-
### Patch Changes
|
16
|
-
|
17
|
-
- @modern-js/builder-doc@2.32.1
|
18
|
-
|
19
|
-
## 2.32.0
|
20
|
-
|
21
|
-
### Patch Changes
|
22
|
-
|
23
|
-
- Updated dependencies [0cc3981]
|
24
|
-
- @modern-js/builder-doc@2.32.0
|
25
|
-
|
26
|
-
## 2.31.2
|
27
|
-
|
28
|
-
### Patch Changes
|
29
|
-
|
30
|
-
- @modern-js/builder-doc@2.31.2
|
31
|
-
|
32
|
-
## 2.31.1
|
33
|
-
|
34
|
-
### Patch Changes
|
35
|
-
|
36
|
-
- 7c4698f: fix(main-doc): modify the correct NoSSR import mode
|
37
|
-
|
38
|
-
fix(main-doc): 修复 NoSSR 组件引入找不到
|
39
|
-
|
40
|
-
- @modern-js/builder-doc@2.31.1
|
41
|
-
|
42
|
-
## 2.31.0
|
43
|
-
|
44
|
-
### Patch Changes
|
45
|
-
|
46
|
-
- @modern-js/builder-doc@2.31.0
|
47
|
-
|
48
|
-
## 2.30.0
|
49
|
-
|
50
|
-
### Patch Changes
|
51
|
-
|
52
|
-
- cc5f49e: feat(builder): add performance.transformLodash config
|
53
|
-
|
54
|
-
feat(builder): 新增 performance.transformLodash 配置
|
55
|
-
|
56
|
-
- Updated dependencies [cc5f49e]
|
57
|
-
- @modern-js/builder-doc@2.30.0
|
58
|
-
|
59
|
-
## 2.29.0
|
60
|
-
|
61
|
-
### Patch Changes
|
62
|
-
|
63
|
-
- @modern-js/builder-doc@2.29.0
|
64
|
-
|
65
|
-
## 2.28.0
|
66
|
-
|
67
|
-
### Patch Changes
|
68
|
-
|
69
|
-
- @modern-js/builder-doc@2.28.0
|
70
|
-
|
71
|
-
## 2.27.0
|
72
|
-
|
73
|
-
### Patch Changes
|
74
|
-
|
75
|
-
- 86274f5: docs: add source code build documentation
|
76
|
-
docs: 添加源码构建文档
|
77
|
-
- ebdc4da: Fixed markdown error for link to styled-components website
|
78
|
-
- Updated dependencies [86274f5]
|
79
|
-
- @modern-js/builder-doc@2.27.0
|
80
|
-
|
81
|
-
## 2.26.0
|
82
|
-
|
83
|
-
### Patch Changes
|
84
|
-
|
85
|
-
- @modern-js/builder-doc@2.26.0
|
86
|
-
|
87
|
-
## 2.25.2
|
88
|
-
|
89
|
-
### Patch Changes
|
90
|
-
|
91
|
-
- 4a83fcd: docs(main-doc): fix wrong links and add missing files
|
92
|
-
docs(main-doc): 修复错误的链接,补充缺失的文件
|
93
|
-
- @modern-js/builder-doc@2.25.2
|
94
|
-
|
95
|
-
## 2.25.1
|
96
|
-
|
97
|
-
### Patch Changes
|
98
|
-
|
99
|
-
- @modern-js/builder-doc@2.25.1
|
100
|
-
|
101
|
-
## 2.25.0
|
102
|
-
|
103
|
-
### Patch Changes
|
104
|
-
|
105
|
-
- @modern-js/builder-doc@2.25.0
|
106
|
-
|
107
|
-
## 2.24.0
|
108
|
-
|
109
|
-
### Patch Changes
|
110
|
-
|
111
|
-
- @modern-js/builder-doc@2.24.0
|
112
|
-
|
113
|
-
## 2.23.1
|
114
|
-
|
115
|
-
### Patch Changes
|
116
|
-
|
117
|
-
- Updated dependencies [4d4dca0]
|
118
|
-
- @modern-js/builder-doc@2.23.1
|
119
|
-
|
120
|
-
## 2.23.0
|
121
|
-
|
122
|
-
### Patch Changes
|
123
|
-
|
124
|
-
- 8a93276: docs(main): update basic features alias doc
|
125
|
-
|
126
|
-
docs(main): 更新基础功能 -- 别名文档
|
127
|
-
|
128
|
-
- 7e6fb5f: chore: publishConfig add provenance config
|
129
|
-
|
130
|
-
chore: publishConfig 增加 provenance 配置
|
131
|
-
|
132
|
-
- 372b950: docs(main): update plugin config doc
|
133
|
-
|
134
|
-
docs(main): 更新插件配置文档
|
135
|
-
|
136
|
-
- f28b485: docs(main): update faq doc
|
137
|
-
|
138
|
-
docs(main): 更新 faq 文档
|
139
|
-
|
140
|
-
- f264c4a: docs(main): update html template doc
|
141
|
-
|
142
|
-
docs(main): 更新 HTML 模板文档
|
143
|
-
|
144
|
-
- 5cba7c4: docs(main): update bff config doc
|
145
|
-
|
146
|
-
docs(main): 更新 BFF 配置文档
|
147
|
-
|
148
|
-
- ef865f2: docs(main): update config server doc
|
149
|
-
|
150
|
-
docs(main): 更新 server 配置文档
|
151
|
-
|
152
|
-
- 8bb0e14: chore: review code split docs
|
153
|
-
chore: 审查代码分割文档
|
154
|
-
- Updated dependencies [7e6fb5f]
|
155
|
-
- Updated dependencies [692cc0e]
|
156
|
-
- @modern-js/builder-doc@2.23.0
|
157
|
-
|
158
|
-
## 2.22.1
|
159
|
-
|
160
|
-
### Patch Changes
|
161
|
-
|
162
|
-
- 411d047: docs: fix reset command
|
163
|
-
|
164
|
-
docs: 修复 reset command 翻译问题
|
165
|
-
|
166
|
-
- bce7a12: docs(main): update concept doc
|
167
|
-
|
168
|
-
docs(main): 更新核心概念文档
|
169
|
-
|
170
|
-
- 2ede584: docs(main): update start doc
|
171
|
-
|
172
|
-
docs(main): 更新开始文档
|
173
|
-
|
174
|
-
- 7267a1a: docs(main): update changeset doc
|
175
|
-
|
176
|
-
docs(main): 更新包版本管理文档
|
177
|
-
|
178
|
-
- Updated dependencies [bd4b150]
|
179
|
-
- Updated dependencies [2ede584]
|
180
|
-
- @modern-js/builder-doc@2.22.1
|
181
|
-
|
182
|
-
## 2.22.0
|
183
|
-
|
184
|
-
### Minor Changes
|
185
|
-
|
186
|
-
- 7d1b96e: feat(changeset): optimize release note display
|
187
|
-
|
188
|
-
feat(changeset): 优化生成 Release Note 文案
|
189
|
-
|
190
|
-
### Patch Changes
|
191
|
-
|
192
|
-
- 3c3d1e2: docs: update project creation and new command text.
|
193
|
-
|
194
|
-
docs: 更新生成器创建项目和 new 命令文案。
|
195
|
-
|
196
|
-
- Updated dependencies [850cde6]
|
197
|
-
- Updated dependencies [e7a5f94]
|
198
|
-
- @modern-js/builder-doc@2.22.0
|
199
|
-
|
200
|
-
## 2.21.1
|
201
|
-
|
202
|
-
### Patch Changes
|
203
|
-
|
204
|
-
- @modern-js/builder-doc@2.21.1
|
205
|
-
|
206
|
-
## 2.21.0
|
207
|
-
|
208
|
-
### Patch Changes
|
209
|
-
|
210
|
-
- 26dcf3a: chore: bump typescript to v5 in devDependencies
|
211
|
-
|
212
|
-
chore: 升级 devDependencies 中的 typescript 版本到 v5
|
213
|
-
|
214
|
-
- Updated dependencies [1ef03dc]
|
215
|
-
- @modern-js/builder-doc@2.21.0
|
216
|
-
|
217
|
-
## 2.20.0
|
218
|
-
|
219
|
-
### Patch Changes
|
220
|
-
|
221
|
-
- 3c4e0a5: chore(utils): move generateMetaTags method to builder-shared
|
222
|
-
|
223
|
-
chore(utils): 移动 generateMetaTags 方法到 builder-shared
|
224
|
-
|
225
|
-
- 0ce52ad: docs(main): optimize mobile adaptation
|
226
|
-
|
227
|
-
docs(main): 优化移动端适配
|
228
|
-
|
229
|
-
- @modern-js/builder-doc@2.20.0
|
230
|
-
|
231
|
-
## 2.19.1
|
232
|
-
|
233
|
-
### Patch Changes
|
234
|
-
|
235
|
-
- @modern-js/builder-doc@2.19.1
|
236
|
-
|
237
|
-
## 2.19.0
|
238
|
-
|
239
|
-
### Patch Changes
|
240
|
-
|
241
|
-
- @modern-js/builder-doc@2.19.0
|
242
|
-
|
243
|
-
## 2.18.1
|
244
|
-
|
245
|
-
### Patch Changes
|
246
|
-
|
247
|
-
- 21c87bf: feat: bump codesmith packages version
|
248
|
-
|
249
|
-
feat: 升级 codesmith 包版本
|
250
|
-
|
251
|
-
- @modern-js/builder-doc@2.18.1
|
252
|
-
|
253
|
-
## 2.18.0
|
254
|
-
|
255
|
-
### Patch Changes
|
256
|
-
|
257
|
-
- d0a9bf8: chore: improve entry docs, fix ssg docs
|
258
|
-
chore: 优化入口文档,修复 ssg 文档
|
259
|
-
- @modern-js/builder-doc@2.18.0
|
260
|
-
|
261
|
-
## 2.17.1
|
262
|
-
|
263
|
-
### Patch Changes
|
264
|
-
|
265
|
-
- fc76194: chore: comment the doc for runtime and server plugin hooks
|
266
|
-
chore: 注释 runtime 和 server 插件钩子文档
|
267
|
-
- 7d899fb: fix: typo isFileExist
|
268
|
-
|
269
|
-
fix: isFileExist 拼写错误
|
270
|
-
|
271
|
-
- @modern-js/builder-doc@2.17.1
|
272
|
-
|
273
|
-
## 2.17.0
|
274
|
-
|
275
|
-
### Patch Changes
|
276
|
-
|
277
|
-
- @modern-js/builder-doc@2.17.0
|
278
|
-
|
279
|
-
## 2.16.0
|
280
|
-
|
281
|
-
### Patch Changes
|
282
|
-
|
283
|
-
- 63b3538: fix: dev server crashed when prepare api handler failed
|
284
|
-
|
285
|
-
fix: 修复更新 api server 报错导致 dev server 退出的问题
|
286
|
-
|
287
|
-
- fe92de6: fix(builder): browserslist config should not affect node bundles
|
288
|
-
|
289
|
-
fix(builder): 修复 browserslist 配置会对 node 产物生效的问题
|
290
|
-
|
291
|
-
- 4e876ab: chore: package.json include the monorepo-relative directory
|
292
|
-
|
293
|
-
chore: 在 package.json 中声明 monorepo 的子路径
|
294
|
-
|
295
|
-
- Updated dependencies [fe92de6]
|
296
|
-
- Updated dependencies [4e876ab]
|
297
|
-
- @modern-js/builder-doc@2.16.0
|
298
|
-
|
299
|
-
## 2.15.0
|
300
|
-
|
301
|
-
### Patch Changes
|
302
|
-
|
303
|
-
- @modern-js/builder-doc@2.15.0
|
304
|
-
|
305
|
-
## 2.14.0
|
306
|
-
|
307
|
-
### Patch Changes
|
308
|
-
|
309
|
-
- 60a81d0: feat: add ssr.inlineScript for use inline json instead inline script when ssr
|
310
|
-
feat: 添加 ssr.inlineScript 用于在 ssr 模式下使用内联 json 而不是内联脚本
|
311
|
-
- 432ac8b: chore(cli): improve commands descriptions
|
312
|
-
|
313
|
-
chore(cli): 优化命令的描述文案
|
314
|
-
|
315
|
-
- de84d94: feat: add optional dynamic routes docs
|
316
|
-
feat: 添加可选动态路由文档
|
317
|
-
- Updated dependencies [fefd1c5]
|
318
|
-
- Updated dependencies [1f34dba]
|
319
|
-
- Updated dependencies [b965df2]
|
320
|
-
- @modern-js/builder-doc@2.14.0
|
321
|
-
|
322
|
-
## 2.13.4
|
323
|
-
|
324
|
-
### Patch Changes
|
325
|
-
|
326
|
-
- @modern-js/builder-doc@2.13.4
|
327
|
-
|
328
|
-
## 2.13.3
|
329
|
-
|
330
|
-
### Patch Changes
|
331
|
-
|
332
|
-
- Updated dependencies [28583e8]
|
333
|
-
- @modern-js/builder-doc@2.13.3
|
334
|
-
|
335
|
-
## 2.13.2
|
336
|
-
|
337
|
-
### Patch Changes
|
338
|
-
|
339
|
-
- @modern-js/builder-doc@2.13.2
|
340
|
-
|
341
|
-
## 2.13.1
|
342
|
-
|
343
|
-
### Patch Changes
|
344
|
-
|
345
|
-
- @modern-js/builder-doc@2.13.1
|
346
|
-
|
347
|
-
## 2.13.0
|
348
|
-
|
349
|
-
### Patch Changes
|
350
|
-
|
351
|
-
- e91ec97: feat(app-tools): export mergeConfig function
|
352
|
-
|
353
|
-
feat(app-tools): 导出 mergeConfig 函数
|
354
|
-
|
355
|
-
- 42700c1: chore: improve ssr docs, add more use case for node/web code split
|
356
|
-
chore: 优化 ssr 文档,为 node/web 代码分割添加更多使用场景
|
357
|
-
- Updated dependencies [1feacdc]
|
358
|
-
- Updated dependencies [348306d]
|
359
|
-
- Updated dependencies [42700c1]
|
360
|
-
- @modern-js/builder-doc@2.13.0
|
361
|
-
|
362
|
-
## 2.12.0
|
363
|
-
|
364
|
-
### Patch Changes
|
365
|
-
|
366
|
-
- 9e5044d: doc: 修正文档中使用@edenx/runtime 的部分
|
367
|
-
doc: Correct the sections in the document that use @edenx/runtime.
|
368
|
-
- 9328fb9: feat: prebundle theme
|
369
|
-
|
370
|
-
feat: 预打包主题
|
371
|
-
|
372
|
-
- @modern-js/builder-doc@2.12.0
|
373
|
-
|
374
|
-
## 2.11.0
|
375
|
-
|
376
|
-
### Patch Changes
|
377
|
-
|
378
|
-
- a8c08c3: feat: 添加 `source.transformImoprt`
|
379
|
-
|
380
|
-
feat: add `source.transformImoprt`
|
381
|
-
|
382
|
-
- 304c950: fix: translate some chinese to english in en docs
|
383
|
-
fix: 将部分英文文档中的中文翻译为英文
|
384
|
-
- Updated dependencies [a8c08c3]
|
385
|
-
- Updated dependencies [b71cef1]
|
386
|
-
- @modern-js/builder-doc@2.11.0
|
387
|
-
|
388
|
-
## 2.10.0
|
389
|
-
|
390
|
-
### Patch Changes
|
391
|
-
|
392
|
-
- 92d247f: fix: support tools.devServer.header include string[] type, remove get & delete & apply api in hook or middleware api
|
393
|
-
fix: 支持 tools.devServer.header 包含字符串数组类型,移除 Hook 和 Middleware 中对 响应 Cookie 的获取、删除操作
|
394
|
-
- 19e552a: fix: main doc theme
|
395
|
-
|
396
|
-
fix: 首页深色模式问题
|
397
|
-
|
398
|
-
- Updated dependencies [cfdbf80]
|
399
|
-
- @modern-js/builder-doc@2.10.0
|
400
|
-
|
401
|
-
## 2.9.0
|
402
|
-
|
403
|
-
### Patch Changes
|
404
|
-
|
405
|
-
- 7035d5c22f: fix: doc info block not work
|
406
|
-
|
407
|
-
fix: 修复文档站 info 不生效问题
|
408
|
-
|
409
|
-
- @modern-js/builder-doc@2.9.0
|
410
|
-
|
411
|
-
## 2.8.0
|
412
|
-
|
413
|
-
### Patch Changes
|
414
|
-
|
415
|
-
- ea7bb41e30: feat: add custom web server docs
|
416
|
-
feat: 添加自定义 Web Server 文档
|
417
|
-
- 1104a9f18b: feat: support start web service only
|
418
|
-
feat: 支持只启动 web 服务
|
419
|
-
- bd58566b32: Fix Typo
|
420
|
-
|
421
|
-
修复 Typo
|
422
|
-
|
423
|
-
- Updated dependencies [9736c6a43d]
|
424
|
-
- Updated dependencies [2c1151271d]
|
425
|
-
- @modern-js/builder-doc@2.8.0
|