@rsdoctor/client 0.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/config/constants.ts +19 -0
- package/dist/index.html +1 -0
- package/dist/resource/css/35.cd185e57.css +1 -0
- package/dist/resource/css/index.ff20968e.css +1 -0
- package/dist/resource/js/35.1be054fa.js +456 -0
- package/dist/resource/js/35.1be054fa.js.LICENSE.txt +15193 -0
- package/dist/resource/js/index.334311e0.js +150 -0
- package/dist/resource/js/index.334311e0.js.LICENSE.txt +1657 -0
- package/package.json +51 -0
- package/rsbuild.config.ts +163 -0
- package/src/App.tsx +147 -0
- package/src/common/imgs/connection-point.svg +1 -0
- package/src/common/imgs/icon.svg +21 -0
- package/src/common/imgs/webpack.svg +1 -0
- package/src/common/styles/base.scss +6 -0
- package/src/common/styles/theme.scss +3 -0
- package/src/index.tsx +16 -0
- package/src/main.tsx +147 -0
- package/src/router.tsx +43 -0
- package/src/typings/assetsDefinition.d.ts +16 -0
- package/tsconfig.json +13 -0
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rsdoctor/client",
|
|
3
|
+
"version": "0.0.2-beta.0",
|
|
4
|
+
"main": "dist/index.html",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/web-infra-dev/rsdoctor",
|
|
8
|
+
"directory": "packages/client"
|
|
9
|
+
},
|
|
10
|
+
"lint-staged": {
|
|
11
|
+
"*.{js,jsx,ts,tsx,mjs,cjs}": [
|
|
12
|
+
"node --max_old_space_size=8192 ./node_modules/eslint/bin/eslint.js --fix --color --cache --quiet"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"eslintIgnore": [
|
|
16
|
+
"node_modules/",
|
|
17
|
+
"dist/"
|
|
18
|
+
],
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@rsbuild/core": "0.1.9",
|
|
21
|
+
"@rsbuild/plugin-react": "0.1.9",
|
|
22
|
+
"@rsbuild/plugin-node-polyfill": "0.1.9",
|
|
23
|
+
"@rsbuild/plugin-type-check": "0.1.9",
|
|
24
|
+
"@types/node": "^16",
|
|
25
|
+
"@types/react": "^18",
|
|
26
|
+
"@types/react-dom": "^18",
|
|
27
|
+
"@types/serve-static": "1.15.0",
|
|
28
|
+
"@types/webpack": "5.28.0",
|
|
29
|
+
"antd": "5.8.3",
|
|
30
|
+
"normalize.css": "8.0.1",
|
|
31
|
+
"react": "^18",
|
|
32
|
+
"react-dom": "18.2.0",
|
|
33
|
+
"react-error-boundary": "^4.0.11",
|
|
34
|
+
"react-router-dom": "6.4.3",
|
|
35
|
+
"serve-static": "1.15.0",
|
|
36
|
+
"typescript": "^5.2.2",
|
|
37
|
+
"@rsdoctor/components": "0.0.2-beta.0",
|
|
38
|
+
"@rsdoctor/types": "0.0.2-beta.0"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"dev": "rsbuild dev",
|
|
46
|
+
"start": "rsbuild dev",
|
|
47
|
+
"build": "rsbuild build",
|
|
48
|
+
"build:analysis": "ENABLE_DEVTOOLS_PLUGIN=true DEVTOOLS_DEV=true rsbuild build",
|
|
49
|
+
"preview": "rsbuild preview"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type { Compiler } from 'webpack';
|
|
2
|
+
import { defineConfig } from '@rsbuild/core';
|
|
3
|
+
import { pluginReact } from '@rsbuild/plugin-react';
|
|
4
|
+
import { pluginTypeCheck } from '@rsbuild/plugin-type-check';
|
|
5
|
+
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
|
|
6
|
+
import serve from 'serve-static';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import {
|
|
10
|
+
ClientEntry,
|
|
11
|
+
DistPath,
|
|
12
|
+
PortForCLI,
|
|
13
|
+
PortForWeb,
|
|
14
|
+
WebpackDoctorDirPath,
|
|
15
|
+
WebpackStatsFilePath,
|
|
16
|
+
} from './config/constants';
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
ENABLE_DEVTOOLS_PLUGIN,
|
|
20
|
+
OFFICAL_PREVIEW_PUBLIC_PATH,
|
|
21
|
+
OFFICAL_DEMO_MANIFEST_PATH,
|
|
22
|
+
ENABLE_CLIENT_SERVER,
|
|
23
|
+
} = process.env;
|
|
24
|
+
|
|
25
|
+
export default defineConfig((env) => {
|
|
26
|
+
const IS_PRODUCTION = env.env === 'production';
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
plugins: [
|
|
30
|
+
pluginReact(),
|
|
31
|
+
pluginNodePolyfill(),
|
|
32
|
+
pluginTypeCheck({ enable: IS_PRODUCTION }),
|
|
33
|
+
],
|
|
34
|
+
|
|
35
|
+
source: {
|
|
36
|
+
entry: {
|
|
37
|
+
index: ClientEntry,
|
|
38
|
+
},
|
|
39
|
+
define: {
|
|
40
|
+
'process.env.NODE_DEBUG': JSON.stringify(false),
|
|
41
|
+
'process.env.NODE_ENV': JSON.stringify(env.env),
|
|
42
|
+
'process.env.OFFICAL_DEMO_MANIFEST_PATH': JSON.stringify(
|
|
43
|
+
OFFICAL_DEMO_MANIFEST_PATH,
|
|
44
|
+
),
|
|
45
|
+
'process.env.LOCAL_CLI_PORT': JSON.stringify(PortForCLI),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
output: {
|
|
50
|
+
distPath: {
|
|
51
|
+
root: path.basename(DistPath),
|
|
52
|
+
js: 'resource/js',
|
|
53
|
+
css: 'resource/css',
|
|
54
|
+
svg: 'resource/svg',
|
|
55
|
+
font: 'resource/font',
|
|
56
|
+
image: 'resource/image',
|
|
57
|
+
media: 'resource/media',
|
|
58
|
+
},
|
|
59
|
+
assetPrefix: IS_PRODUCTION
|
|
60
|
+
? OFFICAL_PREVIEW_PUBLIC_PATH?.replace(/\/resource$/, '') || '/'
|
|
61
|
+
: '/',
|
|
62
|
+
cleanDistPath: IS_PRODUCTION,
|
|
63
|
+
disableTsChecker: !IS_PRODUCTION,
|
|
64
|
+
disableSourceMap: true,
|
|
65
|
+
disableMinimize: !IS_PRODUCTION,
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
performance: {
|
|
69
|
+
chunkSplit: {
|
|
70
|
+
strategy: 'custom',
|
|
71
|
+
splitChunks: {
|
|
72
|
+
cacheGroups: {
|
|
73
|
+
monaco: {
|
|
74
|
+
test: /node_modules\/monaco-editor\/*/,
|
|
75
|
+
name: 'monaco',
|
|
76
|
+
chunks: 'all',
|
|
77
|
+
maxSize: 1000000,
|
|
78
|
+
minSize: 500000,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
tools: {
|
|
86
|
+
bundlerChain: (chainConfig) => {
|
|
87
|
+
if (ENABLE_DEVTOOLS_PLUGIN) {
|
|
88
|
+
const { RsdoctorRspackPlugin } =
|
|
89
|
+
require('../rspack-plugin/dist') as typeof import('../rspack-plugin/dist');
|
|
90
|
+
|
|
91
|
+
class StatsWriter {
|
|
92
|
+
apply(compiler: Compiler) {
|
|
93
|
+
compiler.hooks.done.tapPromise(
|
|
94
|
+
{ name: 'webpack-stats-json-writer', stage: 99999 },
|
|
95
|
+
async (stats) => {
|
|
96
|
+
const json = stats.toJson({
|
|
97
|
+
all: false,
|
|
98
|
+
assets: true,
|
|
99
|
+
chunks: true,
|
|
100
|
+
modules: true,
|
|
101
|
+
builtAt: true,
|
|
102
|
+
hash: true,
|
|
103
|
+
ids: true,
|
|
104
|
+
version: true,
|
|
105
|
+
entrypoints: true,
|
|
106
|
+
});
|
|
107
|
+
await fs.promises.writeFile(
|
|
108
|
+
WebpackStatsFilePath,
|
|
109
|
+
JSON.stringify(json, null, 2),
|
|
110
|
+
'utf-8',
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
chainConfig.plugin('stats-writer').use(StatsWriter);
|
|
118
|
+
chainConfig.plugin('rsdoctor').use(RsdoctorRspackPlugin, [
|
|
119
|
+
{
|
|
120
|
+
disableClientServer: !ENABLE_CLIENT_SERVER,
|
|
121
|
+
features: {
|
|
122
|
+
loader: true,
|
|
123
|
+
plugins: true,
|
|
124
|
+
resolver: true,
|
|
125
|
+
bundle: true,
|
|
126
|
+
treeShaking: true,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
devServer: {
|
|
134
|
+
historyApiFallback: true,
|
|
135
|
+
setupMiddlewares: [
|
|
136
|
+
(middlewares) => {
|
|
137
|
+
if (fs.existsSync(WebpackDoctorDirPath)) {
|
|
138
|
+
const fn = serve(WebpackDoctorDirPath, {
|
|
139
|
+
index: false,
|
|
140
|
+
setHeaders(res) {
|
|
141
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
middlewares.push(fn);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
html: {
|
|
152
|
+
title: 'Rsdoctor',
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
server: {
|
|
156
|
+
port: PortForWeb,
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
dev: {
|
|
160
|
+
startUrl: ENABLE_CLIENT_SERVER ? undefined : true,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
});
|
package/src/App.tsx
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Constants } from '@rsdoctor/components';
|
|
2
|
+
import { Config, ConfigContext, defaultConfig } from '@rsdoctor/components/config';
|
|
3
|
+
import { Layout } from '@rsdoctor/components/elements';
|
|
4
|
+
import { getDemoUrl, getLocale, setThemeToStorage, setViewModeToStorage, useDetectIfCloudIdeEnv } from '@rsdoctor/components/utils';
|
|
5
|
+
import type { Manifest } from '@rsdoctor/types';
|
|
6
|
+
import { Alert, Button, ConfigProvider, Divider, Result, Space, Typography, theme as te } from 'antd';
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
9
|
+
import { HashRouter as BrowserRouter } from 'react-router-dom';
|
|
10
|
+
import Router from './router';
|
|
11
|
+
// import UploaderComponent from './pages/Resources/Uploader'; TODO: uploader components
|
|
12
|
+
|
|
13
|
+
const { PageState, Theme } = Constants;
|
|
14
|
+
|
|
15
|
+
const App: React.FC = (): React.ReactElement => {
|
|
16
|
+
const ifCloudIdeEnv = useDetectIfCloudIdeEnv();
|
|
17
|
+
|
|
18
|
+
const [state, setState] = useState<Constants.PageState>(PageState.Success);
|
|
19
|
+
const [viewMode, setViewMode] = useState<Config['viewMode']>({ ...defaultConfig.viewMode });
|
|
20
|
+
const [manifest, setManifest] = useState<Manifest.DoctorManifest>();
|
|
21
|
+
const [theme, setTheme] = useState(defaultConfig.theme);
|
|
22
|
+
|
|
23
|
+
if (state === Constants.PageState.Fail) {
|
|
24
|
+
const demoUrl = getDemoUrl();
|
|
25
|
+
return (
|
|
26
|
+
<Space direction="vertical" style={{ padding: 14 }}>
|
|
27
|
+
<Typography.Text strong style={{ fontSize: 16 }}>
|
|
28
|
+
load json file of Rsdoctor failed.
|
|
29
|
+
</Typography.Text>
|
|
30
|
+
<Typography.Text>
|
|
31
|
+
try to use <Typography.Text keyboard>command + r</Typography.Text> to refresh page.
|
|
32
|
+
</Typography.Text>
|
|
33
|
+
{process.env.NODE_ENV === 'development' ? (
|
|
34
|
+
<Typography.Text>
|
|
35
|
+
in development, you need to run <Typography.Text keyboard>emo run build:analysis</Typography.Text> to make
|
|
36
|
+
sure the mock data has been generated.
|
|
37
|
+
</Typography.Text>
|
|
38
|
+
) : null}
|
|
39
|
+
<Divider />
|
|
40
|
+
<Space direction="vertical" style={{ width: '100%' }}>
|
|
41
|
+
<Typography.Text style={{ fontSize: 16 }}>
|
|
42
|
+
you can
|
|
43
|
+
<Typography.Text strong style={{ fontSize: 'inherit' }}>
|
|
44
|
+
{' '}
|
|
45
|
+
upload a file{' '}
|
|
46
|
+
</Typography.Text>
|
|
47
|
+
in the area below to analyze your project.
|
|
48
|
+
</Typography.Text>
|
|
49
|
+
{/* <UploaderComponent /> */}
|
|
50
|
+
</Space>
|
|
51
|
+
<Divider />
|
|
52
|
+
{demoUrl ? (
|
|
53
|
+
<Typography.Text style={{ fontSize: 16 }}>
|
|
54
|
+
or you can open the{' '}
|
|
55
|
+
<Typography.Text strong style={{ fontSize: 'inherit' }}>
|
|
56
|
+
<a href={demoUrl} target="_blank" rel="noreferrer">
|
|
57
|
+
demo
|
|
58
|
+
</a>
|
|
59
|
+
</Typography.Text>{' '}
|
|
60
|
+
to get started with the Rsdoctor.
|
|
61
|
+
</Typography.Text>
|
|
62
|
+
) : null}
|
|
63
|
+
</Space>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<BrowserRouter>
|
|
69
|
+
<ConfigContext.Provider
|
|
70
|
+
value={{
|
|
71
|
+
...defaultConfig,
|
|
72
|
+
theme,
|
|
73
|
+
setTheme: (v) => {
|
|
74
|
+
setTheme(v);
|
|
75
|
+
setThemeToStorage(v);
|
|
76
|
+
},
|
|
77
|
+
pageState: state,
|
|
78
|
+
json: manifest!,
|
|
79
|
+
viewMode,
|
|
80
|
+
setManifest,
|
|
81
|
+
setPageState: setState,
|
|
82
|
+
setViewMode(m, saveStorage = true) {
|
|
83
|
+
const res = { ...viewMode, ...m };
|
|
84
|
+
setViewMode(res);
|
|
85
|
+
saveStorage && setViewModeToStorage(res);
|
|
86
|
+
},
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<ConfigContext.Consumer>
|
|
90
|
+
{(v) => {
|
|
91
|
+
return (
|
|
92
|
+
<ConfigProvider
|
|
93
|
+
locale={getLocale(v.locale)}
|
|
94
|
+
theme={{
|
|
95
|
+
algorithm: theme === Theme.Dark ? te.darkAlgorithm : te.defaultAlgorithm,
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
<Layout>
|
|
99
|
+
<>
|
|
100
|
+
{ifCloudIdeEnv && (
|
|
101
|
+
<Alert
|
|
102
|
+
message="Warning"
|
|
103
|
+
description={
|
|
104
|
+
<a
|
|
105
|
+
href={window.location.href.replace(/https/, 'http')}
|
|
106
|
+
>{`Please jump to:${window.location.href.replace(/https/, 'http')}`}</a>
|
|
107
|
+
}
|
|
108
|
+
type="warning"
|
|
109
|
+
showIcon
|
|
110
|
+
closable
|
|
111
|
+
/>
|
|
112
|
+
)}
|
|
113
|
+
<ErrorBoundary
|
|
114
|
+
FallbackComponent={({ error, resetErrorBoundary }) => (
|
|
115
|
+
<Result
|
|
116
|
+
status="error"
|
|
117
|
+
title="Sorry, something went wrong."
|
|
118
|
+
extra={
|
|
119
|
+
<Button type="primary" onClick={resetErrorBoundary} loading={state === PageState.Pending}>
|
|
120
|
+
Reload
|
|
121
|
+
</Button>
|
|
122
|
+
}
|
|
123
|
+
>
|
|
124
|
+
<Typography.Paragraph>
|
|
125
|
+
<Typography.Title level={3}>Error Stack</Typography.Title>
|
|
126
|
+
<pre>{error.stack || error.message}</pre>
|
|
127
|
+
</Typography.Paragraph>
|
|
128
|
+
</Result>
|
|
129
|
+
)}
|
|
130
|
+
onReset={() => {
|
|
131
|
+
window.location.reload();
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
<Router />
|
|
135
|
+
</ErrorBoundary>
|
|
136
|
+
</>
|
|
137
|
+
</Layout>
|
|
138
|
+
</ConfigProvider>
|
|
139
|
+
);
|
|
140
|
+
}}
|
|
141
|
+
</ConfigContext.Consumer>
|
|
142
|
+
</ConfigContext.Provider>
|
|
143
|
+
</BrowserRouter>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export default App;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 24L43 24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M28 4H20C18.8954 4 18 4.89543 18 6V14C18 15.1046 18.8954 16 20 16H28C29.1046 16 30 15.1046 30 14V6C30 4.89543 29.1046 4 28 4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M16 32H8C6.89543 32 6 32.8954 6 34V42C6 43.1046 6.89543 44 8 44H16C17.1046 44 18 43.1046 18 42V34C18 32.8954 17.1046 32 16 32Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M40 32H32C30.8954 32 30 32.8954 30 34V42C30 43.1046 30.8954 44 32 44H40C41.1046 44 42 43.1046 42 42V34C42 32.8954 41.1046 32 40 32Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 24V16" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M36 32V24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 32V24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<svg width="106.000000" height="113.000000" viewBox="0 0 106 113" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
2
|
+
<rect id="画板 934" width="106.000000" height="113.000000" fill="#FFFFFF" fill-opacity="0.035"/>
|
|
3
|
+
<g clip-path="url(#clip111_45)">
|
|
4
|
+
<rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#0F0D0D"/>
|
|
5
|
+
<rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#736C6C"/>
|
|
6
|
+
<rect id="矩形 2176" x="22.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" stroke="#000000" stroke-linejoin="bevel"/>
|
|
7
|
+
<rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#0F0D0D"/>
|
|
8
|
+
<rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" fill="#736C6C"/>
|
|
9
|
+
<rect id="矩形 2176" x="49.500000" y="10.500000" rx="3.000000" width="6.000000" height="11.000000" stroke="#000000" stroke-linejoin="bevel"/>
|
|
10
|
+
<path id="矢量 943" d="M24.0938 15.8218C24.0938 15.8218 14 11.3477 14 23.2773C14 35.207 26.1123 70 26.1123 70L41 70" stroke="#000000" stroke-width="5.000000"/>
|
|
11
|
+
<path id="矢量 943" d="M53.9062 15.8218C53.9062 15.8218 64 11.3477 64 23.2773C64 35.207 51.8877 70 51.8877 70L37 70" stroke="#000000" stroke-width="5.000000"/>
|
|
12
|
+
<path id="矢量 945" d="M40 83.0723C40 94.0781 48.9219 103 59.9277 103L70 103C81.0459 103 90 94.0459 90 83L90 48" stroke="#000000" stroke-width="5.000000"/>
|
|
13
|
+
<ellipse id="椭圆 54" cx="90.000000" cy="41.500000" rx="11.000000" ry="8.500000" fill="#5092FF"/>
|
|
14
|
+
<path id="矢量 946" d="M27 72C31.9609 80.7266 34.5361 81.2817 39.4443 80.9219C44.7744 81.2124 47.4326 79.7798 51 72" stroke="#000000" stroke-width="5.000000"/>
|
|
15
|
+
</g>
|
|
16
|
+
<defs>
|
|
17
|
+
<clipPath id="clip111_45">
|
|
18
|
+
<rect id="画板 934" width="106.000000" height="113.000000" fill="white"/>
|
|
19
|
+
</clipPath>
|
|
20
|
+
</defs>
|
|
21
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg"><path d="m600 0 530.3 300v600l-530.3 300-530.3-300v-600z" fill="#fff"/><path d="m1035.6 879.3-418.1 236.5v-184.2l260.5-143.3zm28.6-25.9v-494.6l-153 88.3v317.9zm-901.5 25.9 418.1 236.5v-184.2l-260.5-143.3zm-28.6-25.9v-494.6l153 88.3v317.9zm17.9-526.6 428.8-242.6v178.1l-274.7 151.1-2.1 1.2zm894.3 0-428.8-242.6v178.1l274.7 151.1 2.1 1.2z" fill="#8ed6fb"/><path d="m580.8 889.7-257-141.3v-280l257 148.4zm36.7 0 257-141.3v-280l-257 148.4zm-276.3-453.7 258-141.9 258 141.9-258 149z" fill="#1c78c0"/></svg>
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import '@rsdoctor/components/i18n';
|
|
2
|
+
import App from './App';
|
|
3
|
+
import ReactDOM from 'react-dom/client';
|
|
4
|
+
import './common/styles/base.scss';
|
|
5
|
+
import icon from './common/imgs/icon.svg';
|
|
6
|
+
|
|
7
|
+
const rootElement = document.getElementById('root');
|
|
8
|
+
const root = ReactDOM.createRoot(rootElement!);
|
|
9
|
+
|
|
10
|
+
root.render(<App />);
|
|
11
|
+
|
|
12
|
+
const link = document.createElement('link');
|
|
13
|
+
link.setAttribute('type', 'image/x-icon');
|
|
14
|
+
link.setAttribute('rel', 'icon');
|
|
15
|
+
link.setAttribute('href', icon);
|
|
16
|
+
document.head.appendChild(link);
|
package/src/main.tsx
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Constants } from '@rsdoctor/components';
|
|
2
|
+
import { Config, ConfigContext, defaultConfig } from '@rsdoctor/components/config';
|
|
3
|
+
import { Layout } from '@rsdoctor/components/elements';
|
|
4
|
+
import { getDemoUrl, getLocale, setThemeToStorage, setViewModeToStorage, useDetectIfCloudIdeEnv } from '@rsdoctor/components/utils';
|
|
5
|
+
import type { Manifest } from '@rsdoctor/types';
|
|
6
|
+
import { Alert, Button, ConfigProvider, Divider, Result, Space, Typography, theme as te } from 'antd';
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
9
|
+
import { HashRouter as BrowserRouter } from 'react-router-dom';
|
|
10
|
+
import Router from './router';
|
|
11
|
+
// import UploaderComponent from './pages/Resources/Uploader'; TODO: uploader components
|
|
12
|
+
|
|
13
|
+
const { PageState, Theme } = Constants;
|
|
14
|
+
|
|
15
|
+
const Index: React.FC = (): React.ReactElement => {
|
|
16
|
+
const ifCloudIdeEnv = useDetectIfCloudIdeEnv();
|
|
17
|
+
|
|
18
|
+
const [state, setState] = useState<Constants.PageState>(PageState.Success);
|
|
19
|
+
const [viewMode, setViewMode] = useState<Config['viewMode']>({ ...defaultConfig.viewMode });
|
|
20
|
+
const [manifest, setManifest] = useState<Manifest.DoctorManifest>();
|
|
21
|
+
const [theme, setTheme] = useState(defaultConfig.theme);
|
|
22
|
+
|
|
23
|
+
if (state === Constants.PageState.Fail) {
|
|
24
|
+
const demoUrl = getDemoUrl();
|
|
25
|
+
return (
|
|
26
|
+
<Space direction="vertical" style={{ padding: 14 }}>
|
|
27
|
+
<Typography.Text strong style={{ fontSize: 16 }}>
|
|
28
|
+
load json file of Rsdoctor failed.
|
|
29
|
+
</Typography.Text>
|
|
30
|
+
<Typography.Text>
|
|
31
|
+
try to use <Typography.Text keyboard>command + r</Typography.Text> to refresh page.
|
|
32
|
+
</Typography.Text>
|
|
33
|
+
{process.env.NODE_ENV === 'development' ? (
|
|
34
|
+
<Typography.Text>
|
|
35
|
+
in development, you need to run <Typography.Text keyboard>emo run build:analysis</Typography.Text> to make
|
|
36
|
+
sure the mock data has been generated.
|
|
37
|
+
</Typography.Text>
|
|
38
|
+
) : null}
|
|
39
|
+
<Divider />
|
|
40
|
+
<Space direction="vertical" style={{ width: '100%' }}>
|
|
41
|
+
<Typography.Text style={{ fontSize: 16 }}>
|
|
42
|
+
you can
|
|
43
|
+
<Typography.Text strong style={{ fontSize: 'inherit' }}>
|
|
44
|
+
{' '}
|
|
45
|
+
upload a file{' '}
|
|
46
|
+
</Typography.Text>
|
|
47
|
+
in the area below to analyze your project.
|
|
48
|
+
</Typography.Text>
|
|
49
|
+
{/* <UploaderComponent /> */}
|
|
50
|
+
</Space>
|
|
51
|
+
<Divider />
|
|
52
|
+
{demoUrl ? (
|
|
53
|
+
<Typography.Text style={{ fontSize: 16 }}>
|
|
54
|
+
or you can open the{' '}
|
|
55
|
+
<Typography.Text strong style={{ fontSize: 'inherit' }}>
|
|
56
|
+
<a href={demoUrl} target="_blank" rel="noreferrer">
|
|
57
|
+
demo
|
|
58
|
+
</a>
|
|
59
|
+
</Typography.Text>{' '}
|
|
60
|
+
to get started with the Rsdoctor.
|
|
61
|
+
</Typography.Text>
|
|
62
|
+
) : null}
|
|
63
|
+
</Space>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<BrowserRouter>
|
|
69
|
+
<ConfigContext.Provider
|
|
70
|
+
value={{
|
|
71
|
+
...defaultConfig,
|
|
72
|
+
theme,
|
|
73
|
+
setTheme: (v) => {
|
|
74
|
+
setTheme(v);
|
|
75
|
+
setThemeToStorage(v);
|
|
76
|
+
},
|
|
77
|
+
pageState: state,
|
|
78
|
+
json: manifest!,
|
|
79
|
+
viewMode,
|
|
80
|
+
setManifest,
|
|
81
|
+
setPageState: setState,
|
|
82
|
+
setViewMode(m, saveStorage = true) {
|
|
83
|
+
const res = { ...viewMode, ...m };
|
|
84
|
+
setViewMode(res);
|
|
85
|
+
saveStorage && setViewModeToStorage(res);
|
|
86
|
+
},
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<ConfigContext.Consumer>
|
|
90
|
+
{(v) => {
|
|
91
|
+
return (
|
|
92
|
+
<ConfigProvider
|
|
93
|
+
locale={getLocale(v.locale)}
|
|
94
|
+
theme={{
|
|
95
|
+
algorithm: theme === Theme.Dark ? te.darkAlgorithm : te.defaultAlgorithm,
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
<Layout>
|
|
99
|
+
<>
|
|
100
|
+
{ifCloudIdeEnv && (
|
|
101
|
+
<Alert
|
|
102
|
+
message="Warning"
|
|
103
|
+
description={
|
|
104
|
+
<a
|
|
105
|
+
href={window.location.href.replace(/https/, 'http')}
|
|
106
|
+
>{`Please jump to:${window.location.href.replace(/https/, 'http')}`}</a>
|
|
107
|
+
}
|
|
108
|
+
type="warning"
|
|
109
|
+
showIcon
|
|
110
|
+
closable
|
|
111
|
+
/>
|
|
112
|
+
)}
|
|
113
|
+
<ErrorBoundary
|
|
114
|
+
FallbackComponent={({ error, resetErrorBoundary }) => (
|
|
115
|
+
<Result
|
|
116
|
+
status="error"
|
|
117
|
+
title="Sorry, something went wrong."
|
|
118
|
+
extra={
|
|
119
|
+
<Button type="primary" onClick={resetErrorBoundary} loading={state === PageState.Pending}>
|
|
120
|
+
Reload
|
|
121
|
+
</Button>
|
|
122
|
+
}
|
|
123
|
+
>
|
|
124
|
+
<Typography.Paragraph>
|
|
125
|
+
<Typography.Title level={3}>Error Stack</Typography.Title>
|
|
126
|
+
<pre>{error.stack || error.message}</pre>
|
|
127
|
+
</Typography.Paragraph>
|
|
128
|
+
</Result>
|
|
129
|
+
)}
|
|
130
|
+
onReset={() => {
|
|
131
|
+
window.location.reload();
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
<Router />
|
|
135
|
+
</ErrorBoundary>
|
|
136
|
+
</>
|
|
137
|
+
</Layout>
|
|
138
|
+
</ConfigProvider>
|
|
139
|
+
);
|
|
140
|
+
}}
|
|
141
|
+
</ConfigContext.Consumer>
|
|
142
|
+
</ConfigContext.Provider>
|
|
143
|
+
</BrowserRouter>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export default Index;
|
package/src/router.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Route, Routes } from 'react-router-dom';
|
|
3
|
+
import { Overall, BundleSize, LoaderFiles, PluginsAnalyze, ModuleResolve, LoaderTimeline } from '@rsdoctor/components/pages';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default function Router(): React.ReactElement {
|
|
7
|
+
const routes = [
|
|
8
|
+
{
|
|
9
|
+
path: BundleSize.route,
|
|
10
|
+
element: <BundleSize.Page />,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
path: LoaderFiles.route,
|
|
14
|
+
element: <LoaderFiles.Page />,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
path: LoaderFiles.route,
|
|
18
|
+
element: <LoaderFiles.Page />,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
path: PluginsAnalyze.route,
|
|
22
|
+
element: <PluginsAnalyze.Page />,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
path: ModuleResolve.route,
|
|
26
|
+
element: <ModuleResolve.Page />,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
path: LoaderTimeline.route,
|
|
30
|
+
element: <LoaderTimeline.Page />,
|
|
31
|
+
},
|
|
32
|
+
].filter((e) => Boolean(e)) as { path: string; element: JSX.Element }[];
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Routes>
|
|
36
|
+
<Route path="/" element={<Overall.Page />} />
|
|
37
|
+
<Route path={Overall.route} element={<Overall.Page />} />
|
|
38
|
+
{routes.map((e) => (
|
|
39
|
+
<Route key={e.path} path={e.path} element={e.element} />
|
|
40
|
+
))}
|
|
41
|
+
</Routes>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare module '*.png';
|
|
2
|
+
declare module '*.jpg';
|
|
3
|
+
declare module '*.svg';
|
|
4
|
+
declare module '*.jpeg';
|
|
5
|
+
declare module '*.gif';
|
|
6
|
+
declare module '*.webp';
|
|
7
|
+
declare module '*.ttf';
|
|
8
|
+
declare module '*.woff';
|
|
9
|
+
declare module '*.woff2';
|
|
10
|
+
declare module '*.scss';
|
|
11
|
+
declare module '*.less';
|
|
12
|
+
declare module '*.css';
|
|
13
|
+
declare module '*?__inline';
|
|
14
|
+
declare module '*?__inline=true';
|
|
15
|
+
declare module '*?__inline=false';
|
|
16
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@rsdoctor/tsconfig/base",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": "./",
|
|
5
|
+
"jsx": "react-jsx",
|
|
6
|
+
"isolatedModules": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"composite": true,
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
},
|
|
11
|
+
"include": ["src", "config"],
|
|
12
|
+
"exclude": ["**/node_modules"]
|
|
13
|
+
}
|