@forge-kit/plugin-json-viewer 0.0.1
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/README.md +73 -0
- package/dist/app.js +98 -0
- package/dist/icon.svg +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +46 -0
- package/src/App.less +44 -0
- package/src/App.tsx +238 -0
- package/src/icon.svg +1 -0
- package/src/main.tsx +30 -0
package/dist/icon.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763716801467" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1687" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M213.333333 128h85.333334v85.333333H213.333333v213.333334a85.333333 85.333333 0 0 1-85.333333 85.333333 85.333333 85.333333 0 0 1 85.333333 85.333333v213.333334h85.333334v85.333333H213.333333c-45.653333-11.52-85.333333-38.4-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 0-85.333333-85.333333H0v-85.333334h42.666667a85.333333 85.333333 0 0 0 85.333333-85.333333V213.333333a85.333333 85.333333 0 0 1 85.333333-85.333333m597.333334 0a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h42.666667v85.333334h-42.666667a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-85.333334v-85.333333h85.333334v-213.333334a85.333333 85.333333 0 0 1 85.333333-85.333333 85.333333 85.333333 0 0 1-85.333333-85.333333V213.333333h-85.333334V128h85.333334m-298.666667 512a42.666667 42.666667 0 0 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667 42.666666 42.666667 42.666667 0 0 1-42.666667-42.666666 42.666667 42.666667 0 0 1 42.666667-42.666667m-170.666667 0a42.666667 42.666667 0 0 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667 42.666666 42.666667 42.666667 0 0 1-42.666666-42.666666 42.666667 42.666667 0 0 1 42.666666-42.666667m341.333334 0a42.666667 42.666667 0 0 1 42.666666 42.666667 42.666667 42.666667 0 0 1-42.666666 42.666666 42.666667 42.666667 0 0 1-42.666667-42.666666 42.666667 42.666667 0 0 1 42.666667-42.666667z" fill="" p-id="1688"></path></svg>
|
package/dist/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forge-kit/plugin-json-viewer",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"entry": "./dist/app.js",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"author": "yu.pan <panyupy@vip.qq.com>",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "vite",
|
|
17
|
+
"build": "tsc -b && vite build",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"preview": "vite preview"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@forge-kit/component": "workspace:*",
|
|
23
|
+
"@forge-kit/forge-kit": "workspace:*",
|
|
24
|
+
"@forge-kit/icons": "workspace:*",
|
|
25
|
+
"classnames": "^2.5.1",
|
|
26
|
+
"jsonc-parser": "^3.3.1",
|
|
27
|
+
"prettier": "^3.6.2",
|
|
28
|
+
"react": "^19.0.0",
|
|
29
|
+
"react-dom": "^19.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@eslint/js": "^9.39.1",
|
|
33
|
+
"@types/node": "^24.10.0",
|
|
34
|
+
"@types/react": "^19.0.0",
|
|
35
|
+
"@types/react-dom": "^19.0.0",
|
|
36
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
37
|
+
"eslint": "^9.39.1",
|
|
38
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
39
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
40
|
+
"globals": "^16.5.0",
|
|
41
|
+
"typescript": "~5.9.3",
|
|
42
|
+
"typescript-eslint": "^8.46.3",
|
|
43
|
+
"vite": "^7.2.2",
|
|
44
|
+
"@forge-kit/vite-plugin-forge-kit": "workspace:*"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/App.less
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
html, body, #root {
|
|
2
|
+
-webkit-app-region: drag;
|
|
3
|
+
background-color: transparent; /* 保持透明 */
|
|
4
|
+
margin: 0;
|
|
5
|
+
height: 100%;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.forge-kit-plugin-json-viewer {
|
|
10
|
+
width: 100%;
|
|
11
|
+
height: 100%;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
|
|
14
|
+
&-content {
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 100%;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
|
|
19
|
+
.formatted-viewer-card,
|
|
20
|
+
.text-area-card {
|
|
21
|
+
flex: 1;
|
|
22
|
+
|
|
23
|
+
.text-area {
|
|
24
|
+
height: 100%;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.json-viewer-card-layout {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
|
|
32
|
+
.layout-title {
|
|
33
|
+
padding-bottom: var(--space-3);
|
|
34
|
+
border-bottom: solid 1px var(--gray-5);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.layout-content {
|
|
38
|
+
padding-top: var(--space-3);
|
|
39
|
+
flex: 1;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/App.tsx
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import prettier from "prettier/standalone";
|
|
2
|
+
import prettierPluginBabel from "prettier/plugins/babel";
|
|
3
|
+
import prettierPluginEstree from "prettier/plugins/estree";
|
|
4
|
+
import {Flex, TextArea, Text, Box, ScrollArea, Card, Theme} from "@forge-kit/component";
|
|
5
|
+
import {parseTree} from "jsonc-parser";
|
|
6
|
+
import type {Node, NodeType} from "jsonc-parser";
|
|
7
|
+
import React, {useContext, useEffect, useState} from "react";
|
|
8
|
+
import {TriangleRightIcon, FilePlusIcon, FileMinusIcon, MagicWandIcon} from '@forge-kit/icons'
|
|
9
|
+
import type {ComponentProps} from 'react'
|
|
10
|
+
import '@forge-kit/component/style.css'
|
|
11
|
+
import classNames from "classnames";
|
|
12
|
+
import './App.less'
|
|
13
|
+
|
|
14
|
+
type ColorConfig = Partial<Record<NodeType, ComponentProps<typeof Text>['color']>>
|
|
15
|
+
|
|
16
|
+
interface JsonViewerOperate {
|
|
17
|
+
isCollapsed: boolean;
|
|
18
|
+
operateId: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface JsonViewerCtxVal extends JsonViewerOperate {
|
|
22
|
+
isCollapsed: boolean;
|
|
23
|
+
operateId: string;
|
|
24
|
+
colorConfig?: ColorConfig
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const JsonViewerContext = React.createContext<Partial<JsonViewerCtxVal>>({})
|
|
28
|
+
|
|
29
|
+
interface JsonNodeProps {
|
|
30
|
+
label?: string
|
|
31
|
+
jsonNode?: Node
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 渲染JSON节点
|
|
36
|
+
* @param props
|
|
37
|
+
* @constructor
|
|
38
|
+
*/
|
|
39
|
+
const JsonNode: React.FC<JsonNodeProps> = (props) => {
|
|
40
|
+
const {jsonNode} = props
|
|
41
|
+
if (jsonNode?.type === 'object') return <JsonNodeContainer {...props} />
|
|
42
|
+
if (jsonNode?.type === 'array') return <JsonNodeContainer {...props} />
|
|
43
|
+
if (jsonNode?.type === 'property') return <JsonNodeProperty {...props} />
|
|
44
|
+
return <JsonNodeValue {...props} />
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type JsonNodeContainerProps = JsonNodeProps
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 渲染JSON节点容器
|
|
51
|
+
* @param props
|
|
52
|
+
* @constructor
|
|
53
|
+
*/
|
|
54
|
+
const JsonNodeContainer: React.FC<JsonNodeContainerProps> = (props) => {
|
|
55
|
+
const {label, jsonNode} = props
|
|
56
|
+
// 解析JSON节点类型和子节点
|
|
57
|
+
const {type: jsonNodeType, children: jsonNodeChildren = [], parent} = jsonNode || {}
|
|
58
|
+
// 初始化折叠状态为true
|
|
59
|
+
const [isCollapsed, setIsCollapsed] = useState<boolean>(false)
|
|
60
|
+
// 从上下文获取操作ID和折叠状态
|
|
61
|
+
const {operateId, isCollapsed: contextIsCollapsed} = useContext(JsonViewerContext) || {}
|
|
62
|
+
// 判断是否为复杂类型节点(对象或数组)
|
|
63
|
+
const isComplexType = ['object', 'array'].includes(jsonNodeType!)
|
|
64
|
+
// 判断是否为数组节点
|
|
65
|
+
const isArrayNode = jsonNodeType === 'array'
|
|
66
|
+
// 判断是否为根节点
|
|
67
|
+
const isRootNode = Boolean(!parent)
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
setIsCollapsed(Boolean(contextIsCollapsed))
|
|
71
|
+
}, [operateId])
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<Flex direction={isComplexType ? 'column' : 'row'} pl={isRootNode ? '0' : '4'} align="start">
|
|
75
|
+
<Flex align="center" gap="1" mr="1" onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
76
|
+
{/* 渲染JSON节点折叠图标 */}
|
|
77
|
+
<Flex width="16px" align="center">{isComplexType && <TriangleRightIcon width={16} height={16}/>}</Flex>
|
|
78
|
+
{/* 渲染JSON节点标签 */}
|
|
79
|
+
{!isRootNode && <Text color="purple">{label}:</Text>}
|
|
80
|
+
{/* 渲染JSON节点类型 */}
|
|
81
|
+
<Box>
|
|
82
|
+
{/* 渲染JSON节点类型 */}
|
|
83
|
+
{isComplexType && <Text>{jsonNodeType}</Text>}
|
|
84
|
+
{/* 渲染JSON节点数组长度 */}
|
|
85
|
+
{isArrayNode && <Text>({jsonNodeChildren?.length})</Text>}
|
|
86
|
+
</Box>
|
|
87
|
+
</Flex>
|
|
88
|
+
{/* 渲染JSON节点值 */}
|
|
89
|
+
{!isComplexType && <JsonNode jsonNode={jsonNode}/>}
|
|
90
|
+
{/* 渲染JSON节点子节点 */}
|
|
91
|
+
{isComplexType && !isCollapsed && (
|
|
92
|
+
<Flex direction="column">
|
|
93
|
+
{jsonNodeChildren.map((child, index) => {
|
|
94
|
+
// 渲染JSON节点属性
|
|
95
|
+
if (isArrayNode) return <JsonNodeContainer label={String(index)} jsonNode={child}/>
|
|
96
|
+
// 渲染JSON节点数组元素
|
|
97
|
+
return <JsonNode jsonNode={child}/>
|
|
98
|
+
})}
|
|
99
|
+
</Flex>
|
|
100
|
+
)}
|
|
101
|
+
</Flex>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 渲染JSON节点属性
|
|
107
|
+
* @param props
|
|
108
|
+
* @constructor
|
|
109
|
+
*/
|
|
110
|
+
const JsonNodeProperty: React.FC<JsonNodeProps> = (props) => {
|
|
111
|
+
const {jsonNode} = props
|
|
112
|
+
const [key, value] = jsonNode?.children || []
|
|
113
|
+
return <JsonNodeContainer label={key.value} jsonNode={value}/>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 渲染JSON节点值
|
|
118
|
+
* @param props
|
|
119
|
+
* @constructor
|
|
120
|
+
*/
|
|
121
|
+
const JsonNodeValue: React.FC<JsonNodeProps> = (props) => {
|
|
122
|
+
const {jsonNode,} = props
|
|
123
|
+
const {type, value} = jsonNode || {}
|
|
124
|
+
const {colorConfig = {}} = useContext(JsonViewerContext) || {}
|
|
125
|
+
if (!type) return null
|
|
126
|
+
return <Text color={colorConfig[type]}>{type === "string" ? `"${value}"` : String(value)}</Text>
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
interface JsonViewerProps extends JsonNodeProps {
|
|
131
|
+
className?: string
|
|
132
|
+
colorConfig?: ColorConfig
|
|
133
|
+
operate?: Partial<JsonViewerOperate>
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 渲染JSON查看器
|
|
138
|
+
* @param props
|
|
139
|
+
* @constructor
|
|
140
|
+
*/
|
|
141
|
+
const JsonViewer: React.FC<JsonViewerProps> = (props) => {
|
|
142
|
+
const {className, jsonNode, colorConfig, operate = {}} = props
|
|
143
|
+
return (
|
|
144
|
+
<ScrollArea className={className} type="auto" scrollbars="vertical">
|
|
145
|
+
<JsonViewerContext.Provider value={{...operate, colorConfig}}>
|
|
146
|
+
<JsonNode jsonNode={jsonNode}/>
|
|
147
|
+
</JsonViewerContext.Provider>
|
|
148
|
+
</ScrollArea>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
interface CardLayoutProps {
|
|
153
|
+
title?: string
|
|
154
|
+
extra?: React.ReactNode
|
|
155
|
+
className?: string
|
|
156
|
+
children?: React.ReactNode
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const CardLayout: React.FC<CardLayoutProps> = (props) => {
|
|
160
|
+
const {title, extra, className, children} = props
|
|
161
|
+
return (
|
|
162
|
+
<Card className={classNames("json-viewer-card-layout", className)}>
|
|
163
|
+
<Flex className="layout-title" justify="between" align="center">
|
|
164
|
+
<Text size="1">{title}</Text>
|
|
165
|
+
<Flex align="center" gap="2">{extra}</Flex>
|
|
166
|
+
</Flex>
|
|
167
|
+
<Box className="layout-content">{children}</Box>
|
|
168
|
+
</Card>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 默认颜色配置
|
|
174
|
+
*/
|
|
175
|
+
const colorConfig: ColorConfig = {
|
|
176
|
+
string: "green",
|
|
177
|
+
boolean: "orange",
|
|
178
|
+
number: "orange",
|
|
179
|
+
null: "orange",
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const App: React.FC = () => {
|
|
183
|
+
|
|
184
|
+
const [json, setJson] = useState("");
|
|
185
|
+
|
|
186
|
+
const [jsonViewerOperate, setJsonViewerOperate] = useState<Partial<JsonViewerOperate>>({})
|
|
187
|
+
|
|
188
|
+
const errors: any[] = []
|
|
189
|
+
|
|
190
|
+
const result = parseTree(json, errors)
|
|
191
|
+
|
|
192
|
+
const handleFormatJson = async () => {
|
|
193
|
+
const result = await prettier.format(json, {
|
|
194
|
+
parser: "json",
|
|
195
|
+
printWidth: 0,
|
|
196
|
+
plugins: [prettierPluginBabel, prettierPluginEstree],
|
|
197
|
+
})
|
|
198
|
+
return setJson(result)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const handleJsonViewerCollapse = () => {
|
|
202
|
+
const operateId = Date.now().toString(16)
|
|
203
|
+
setJsonViewerOperate({isCollapsed: true, operateId})
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const handleJsonViewerExpand = () => {
|
|
207
|
+
const operateId = Date.now().toString(16)
|
|
208
|
+
setJsonViewerOperate({isCollapsed: false, operateId})
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const handleTextAreaChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
212
|
+
const {value} = event.target
|
|
213
|
+
setJson(value)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const sourceInputExtra = <MagicWandIcon width={18} height={18} onClick={handleFormatJson}/>
|
|
217
|
+
|
|
218
|
+
const parsedTreeViewExtra = (
|
|
219
|
+
<>
|
|
220
|
+
<FilePlusIcon width={18} height={18} onClick={handleJsonViewerExpand}/>
|
|
221
|
+
<FileMinusIcon width={18} height={18} onClick={handleJsonViewerCollapse}/>
|
|
222
|
+
</>
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<Theme className="forge-kit-plugin-json-viewer" accentColor="gray" appearance="dark" radius="full"
|
|
227
|
+
apply={import.meta.env.DEV}>
|
|
228
|
+
<Flex className="forge-kit-plugin-json-viewer-content" gap="4">
|
|
229
|
+
<CardLayout className="text-area-card" title="SOURCE INPUT" extra={sourceInputExtra}>
|
|
230
|
+
<TextArea className="text-area" size="3" value={json} onChange={handleTextAreaChange}/>
|
|
231
|
+
</CardLayout>
|
|
232
|
+
<CardLayout className="formatted-viewer-card" title="PARSED TREE VIEW" extra={parsedTreeViewExtra}>
|
|
233
|
+
<JsonViewer jsonNode={result} colorConfig={colorConfig} operate={jsonViewerOperate}/>
|
|
234
|
+
</CardLayout>
|
|
235
|
+
</Flex>
|
|
236
|
+
</Theme>
|
|
237
|
+
)
|
|
238
|
+
}
|
package/src/icon.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763716801467" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1687" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M213.333333 128h85.333334v85.333333H213.333333v213.333334a85.333333 85.333333 0 0 1-85.333333 85.333333 85.333333 85.333333 0 0 1 85.333333 85.333333v213.333334h85.333334v85.333333H213.333333c-45.653333-11.52-85.333333-38.4-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 0-85.333333-85.333333H0v-85.333334h42.666667a85.333333 85.333333 0 0 0 85.333333-85.333333V213.333333a85.333333 85.333333 0 0 1 85.333333-85.333333m597.333334 0a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 0 85.333333 85.333333h42.666667v85.333334h-42.666667a85.333333 85.333333 0 0 0-85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-85.333334v-85.333333h85.333334v-213.333334a85.333333 85.333333 0 0 1 85.333333-85.333333 85.333333 85.333333 0 0 1-85.333333-85.333333V213.333333h-85.333334V128h85.333334m-298.666667 512a42.666667 42.666667 0 0 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667 42.666666 42.666667 42.666667 0 0 1-42.666667-42.666666 42.666667 42.666667 0 0 1 42.666667-42.666667m-170.666667 0a42.666667 42.666667 0 0 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667 42.666666 42.666667 42.666667 0 0 1-42.666666-42.666666 42.666667 42.666667 0 0 1 42.666666-42.666667m341.333334 0a42.666667 42.666667 0 0 1 42.666666 42.666667 42.666667 42.666667 0 0 1-42.666666 42.666666 42.666667 42.666667 0 0 1-42.666667-42.666666 42.666667 42.666667 0 0 1 42.666667-42.666667z" fill="" p-id="1688"></path></svg>
|
package/src/main.tsx
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {StrictMode} from 'react'
|
|
2
|
+
import ReactDOM from "react-dom/client";
|
|
3
|
+
import {definePlugin} from '@forge-kit/forge-kit'
|
|
4
|
+
import {App} from './App.tsx'
|
|
5
|
+
|
|
6
|
+
let rootInstance: ReturnType<typeof ReactDOM.createRoot> | null = null;
|
|
7
|
+
|
|
8
|
+
const plugin = definePlugin({
|
|
9
|
+
bundleId: "com.forge-kit.plugin.json-viewer",
|
|
10
|
+
name: 'JSON 解析工具',
|
|
11
|
+
icon: `${import.meta.env.BASE_URL}icon.svg`,
|
|
12
|
+
description: "JSON 解析工具",
|
|
13
|
+
mount: (container: any) => {
|
|
14
|
+
rootInstance = ReactDOM.createRoot(container);
|
|
15
|
+
rootInstance.render(
|
|
16
|
+
<StrictMode>
|
|
17
|
+
<App/>
|
|
18
|
+
</StrictMode>,
|
|
19
|
+
)
|
|
20
|
+
},
|
|
21
|
+
unmount: () => {
|
|
22
|
+
if (!rootInstance) return
|
|
23
|
+
rootInstance.unmount();
|
|
24
|
+
rootInstance = null;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
if (import.meta.env.DEV) plugin.mount(document.getElementById('root')!)
|
|
28
|
+
|
|
29
|
+
export default plugin
|
|
30
|
+
|