@gant-lowcode/plugin-code-generator 0.0.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/README.md +23 -0
- package/dist/components/code-gen-action/index.css +18 -0
- package/dist/components/code-gen-action/index.d.ts +6 -0
- package/dist/components/code-gen-action/index.js +143 -0
- package/dist/components/code-gen-preview/fixPreviewCode.d.ts +2 -0
- package/dist/components/code-gen-preview/fixPreviewCode.js +119 -0
- package/dist/components/code-gen-preview/index.css +18 -0
- package/dist/components/code-gen-preview/index.d.ts +8 -0
- package/dist/components/code-gen-preview/index.js +9 -0
- package/dist/components/code-gen-result/index.css +18 -0
- package/dist/components/code-gen-result/index.d.ts +8 -0
- package/dist/components/code-gen-result/index.js +162 -0
- package/dist/components/codesandbox-preview/index.css +17 -0
- package/dist/components/codesandbox-preview/index.d.ts +3 -0
- package/dist/components/codesandbox-preview/index.js +147 -0
- package/dist/components/file-tree/index.css +55 -0
- package/dist/components/file-tree/index.d.ts +20 -0
- package/dist/components/file-tree/index.js +139 -0
- package/dist/components/file-type-icon/index.css +61 -0
- package/dist/components/file-type-icon/index.d.ts +6 -0
- package/dist/components/file-type-icon/index.js +10 -0
- package/dist/components/sources-view/index.css +11 -0
- package/dist/components/sources-view/index.d.ts +7 -0
- package/dist/components/sources-view/index.js +128 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +50 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/index.js +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__ from "react/jsx-runtime";
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
|
|
3
|
+
import * as __WEBPACK_EXTERNAL_MODULE_antd__ from "antd";
|
|
4
|
+
import * as __WEBPACK_EXTERNAL_MODULE__code_gen_preview_fixPreviewCode_js__ from "../code-gen-preview/fixPreviewCode.js";
|
|
5
|
+
import "./index.css";
|
|
6
|
+
// 使用 CodeSandbox 来进行预览
|
|
7
|
+
// @see https://codesandbox.io/docs/api#get-request
|
|
8
|
+
function CodeSandboxPreview({ code, height }) {
|
|
9
|
+
const parameters = (0, __WEBPACK_EXTERNAL_MODULE_react__.useMemo)(()=>{
|
|
10
|
+
const files = {};
|
|
11
|
+
if (code && code.modules) {
|
|
12
|
+
const fixedCode = (0, __WEBPACK_EXTERNAL_MODULE__code_gen_preview_fixPreviewCode_js__.fixPreviewCode)(code);
|
|
13
|
+
if (fixedCode) Object.values(fixedCode.modules).forEach((file)=>{
|
|
14
|
+
files[file?.fpath?.slice(1)] = {
|
|
15
|
+
isBinary: false,
|
|
16
|
+
content: file.code
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
// 入口文件需要顺便引入下样式
|
|
20
|
+
files["src/index.js"] = {
|
|
21
|
+
isBinary: false,
|
|
22
|
+
content: `
|
|
23
|
+
// 目前需要单独引入下样式文件
|
|
24
|
+
import "@alifd/next/dist/next.css";
|
|
25
|
+
import "@alifd/pro-layout/dist/AlifdProLayout.css";
|
|
26
|
+
|
|
27
|
+
// 引入入口文件
|
|
28
|
+
import './app';
|
|
29
|
+
`
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
files,
|
|
34
|
+
template: "create-react-app"
|
|
35
|
+
};
|
|
36
|
+
}, [
|
|
37
|
+
code
|
|
38
|
+
]);
|
|
39
|
+
const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)({
|
|
40
|
+
parameters,
|
|
41
|
+
sandboxId: "",
|
|
42
|
+
isCreating: false,
|
|
43
|
+
hasError: false,
|
|
44
|
+
error: null
|
|
45
|
+
});
|
|
46
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
47
|
+
if (state.parameters !== parameters || "retry" === state.sandboxId || !state.sandboxId) {
|
|
48
|
+
let hasCanceled = false;
|
|
49
|
+
setState((prev)=>({
|
|
50
|
+
...prev,
|
|
51
|
+
hasError: false,
|
|
52
|
+
code,
|
|
53
|
+
parameters,
|
|
54
|
+
isCreating: true
|
|
55
|
+
}));
|
|
56
|
+
(async ()=>{
|
|
57
|
+
try {
|
|
58
|
+
const sandboxId = await createCodeSandbox(parameters);
|
|
59
|
+
if (!hasCanceled) setState((prev)=>({
|
|
60
|
+
...prev,
|
|
61
|
+
hasError: false,
|
|
62
|
+
isCreating: false,
|
|
63
|
+
sandboxId: sandboxId
|
|
64
|
+
}));
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (!hasCanceled) setState((prev)=>({
|
|
67
|
+
...prev,
|
|
68
|
+
hasError: true,
|
|
69
|
+
error,
|
|
70
|
+
isCreating: false
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
return ()=>{
|
|
75
|
+
hasCanceled = true;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return ()=>{};
|
|
79
|
+
}, [
|
|
80
|
+
parameters,
|
|
81
|
+
state.sandboxId,
|
|
82
|
+
state.parameters
|
|
83
|
+
]);
|
|
84
|
+
const handleRetry = ()=>{
|
|
85
|
+
setState((prev)=>({
|
|
86
|
+
...prev,
|
|
87
|
+
hasError: false,
|
|
88
|
+
sandboxId: "retry"
|
|
89
|
+
}));
|
|
90
|
+
};
|
|
91
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("div", {
|
|
92
|
+
className: "code-gen-plugin-code-sandbox-preview",
|
|
93
|
+
style: {
|
|
94
|
+
height
|
|
95
|
+
},
|
|
96
|
+
"data-code-sandbox-id": state.sandboxId,
|
|
97
|
+
children: (()=>{
|
|
98
|
+
if (state.hasError) return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_antd__.Alert, {
|
|
99
|
+
message: "生成 CodeSandbox 预览应用失败",
|
|
100
|
+
description: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsxs)(__WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.Fragment, {
|
|
101
|
+
children: [
|
|
102
|
+
/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsxs)("p", {
|
|
103
|
+
children: [
|
|
104
|
+
"详细错误:",
|
|
105
|
+
`${state.error || "网络开小差了"}`
|
|
106
|
+
]
|
|
107
|
+
}),
|
|
108
|
+
/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("p", {
|
|
109
|
+
children: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_antd__.Button, {
|
|
110
|
+
onClick: handleRetry,
|
|
111
|
+
children: "重新尝试下"
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
]
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
return state.sandboxId ? /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("iframe", {
|
|
118
|
+
src: `https://codesandbox.io/embed/${state.sandboxId}?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview`,
|
|
119
|
+
title: "CodeSandbox Preview",
|
|
120
|
+
allow: "accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",
|
|
121
|
+
sandbox: "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
122
|
+
}) : /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_antd__.Spin, {
|
|
123
|
+
spinning: true,
|
|
124
|
+
tip: "正在生成 CodeSandbox 预览应用..."
|
|
125
|
+
});
|
|
126
|
+
})()
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async function createCodeSandbox(parameters) {
|
|
130
|
+
if (!Object.entries(parameters?.files || {}).length) return "";
|
|
131
|
+
const res = await fetch("https://codesandbox.io/api/v1/sandboxes/define?json=1", {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: {
|
|
134
|
+
"Content-Type": "application/json",
|
|
135
|
+
Accept: "application/json"
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify(parameters)
|
|
138
|
+
});
|
|
139
|
+
if (!res.ok) throw new Error(`创建 CodeSandbox 失败,错误码:${res.status} ${res.statusText}`);
|
|
140
|
+
const json = await res.json().catch((err)=>{
|
|
141
|
+
throw new Error(`创建 CodeSandbox 失败,服务异常(${err?.message || err || "未知异常"})`);
|
|
142
|
+
});
|
|
143
|
+
const { sandbox_id } = json || {};
|
|
144
|
+
if (!sandbox_id || "string" != typeof sandbox_id) throw new Error(`创建 CodeSandbox 失败,服务响应异常`);
|
|
145
|
+
return sandbox_id;
|
|
146
|
+
}
|
|
147
|
+
export { CodeSandboxPreview };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
.code-file-tree {
|
|
2
|
+
white-space: nowrap;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.code-file-tree .tree-node {
|
|
6
|
+
-webkit-user-select: none;
|
|
7
|
+
user-select: none;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
align-items: center;
|
|
10
|
+
display: flex;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.code-file-tree .tree-node:hover, .code-file-tree .tree-node.tree-node-selected {
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
background-color: #cfd0d1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.code-file-tree .tree-item {
|
|
19
|
+
justify-content: left;
|
|
20
|
+
align-items: center;
|
|
21
|
+
display: flex;
|
|
22
|
+
position: absolute;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.code-file-tree .tree-item > i {
|
|
26
|
+
margin-right: 8px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.code-file-tree .tree-item .label-name {
|
|
30
|
+
text-overflow: ellipsis;
|
|
31
|
+
flex: 1;
|
|
32
|
+
min-width: 0;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.code-file-tree .tree-folder:after {
|
|
37
|
+
content: "";
|
|
38
|
+
opacity: .7;
|
|
39
|
+
border-top: 6px solid #000000b3;
|
|
40
|
+
border-left: 6px solid #0000;
|
|
41
|
+
border-right: 6px solid #0000;
|
|
42
|
+
width: 0;
|
|
43
|
+
height: 0;
|
|
44
|
+
margin-left: 20px;
|
|
45
|
+
transition: transform .3s;
|
|
46
|
+
display: block;
|
|
47
|
+
position: absolute;
|
|
48
|
+
left: -36px;
|
|
49
|
+
transform: translate(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.code-file-tree .tree-item-expanded:after {
|
|
53
|
+
transform: rotate(-90deg);
|
|
54
|
+
}
|
|
55
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CodeModules } from "../../types";
|
|
2
|
+
import "./index.less";
|
|
3
|
+
interface FileTreeProps {
|
|
4
|
+
modules: CodeModules;
|
|
5
|
+
onSelect?(key: string): void;
|
|
6
|
+
selectedKeys?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare const FileTree: (props: FileTreeProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
type TreeNode = {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
folder: boolean;
|
|
13
|
+
depth: number;
|
|
14
|
+
expanded: boolean;
|
|
15
|
+
};
|
|
16
|
+
export declare function createFlattenTree(data: Record<string, {
|
|
17
|
+
fpath: string;
|
|
18
|
+
code: string;
|
|
19
|
+
}>, expandedKeys: string[]): TreeNode[];
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__ from "react/jsx-runtime";
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
|
|
3
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_window__ from "react-window";
|
|
4
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_virtualized_auto_sizer__ from "react-virtualized-auto-sizer";
|
|
5
|
+
import * as __WEBPACK_EXTERNAL_MODULE_classnames__ from "classnames";
|
|
6
|
+
import * as __WEBPACK_EXTERNAL_MODULE_memoize_one__ from "memoize-one";
|
|
7
|
+
import * as __WEBPACK_EXTERNAL_MODULE_string_natural_compare__ from "string-natural-compare";
|
|
8
|
+
import * as __WEBPACK_EXTERNAL_MODULE__file_type_icon_index_js__ from "../file-type-icon/index.js";
|
|
9
|
+
import "./index.css";
|
|
10
|
+
const FILE_TYPES_ICON_MAP = {
|
|
11
|
+
js: "js",
|
|
12
|
+
jsx: "jsx",
|
|
13
|
+
ts: "ts",
|
|
14
|
+
tsx: "ts",
|
|
15
|
+
json: "json",
|
|
16
|
+
scss: "scss",
|
|
17
|
+
css: "css",
|
|
18
|
+
less: "less",
|
|
19
|
+
tsconfig: "tsconfig",
|
|
20
|
+
html: "html"
|
|
21
|
+
};
|
|
22
|
+
function getFileIcon(file) {
|
|
23
|
+
const type = FILE_TYPES_ICON_MAP[(file || "").split(".").pop() || ""] || "text";
|
|
24
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE__file_type_icon_index_js__.FileTypeIcon, {
|
|
25
|
+
type: type
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const Row = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.memo)(({ data, index, style })=>{
|
|
29
|
+
const { flattenedData, onOpen, onSelect, selectedKeys } = data;
|
|
30
|
+
const node = flattenedData[index];
|
|
31
|
+
const left = 20 * node.depth;
|
|
32
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("div", {
|
|
33
|
+
className: (0, __WEBPACK_EXTERNAL_MODULE_classnames__["default"])("tree-node", {
|
|
34
|
+
"tree-node-selected": selectedKeys?.includes(node.id)
|
|
35
|
+
}),
|
|
36
|
+
style: style,
|
|
37
|
+
onClick: ()=>onOpen(node),
|
|
38
|
+
children: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsxs)("div", {
|
|
39
|
+
className: (0, __WEBPACK_EXTERNAL_MODULE_classnames__["default"])("tree-item", {
|
|
40
|
+
"tree-folder": node.folder,
|
|
41
|
+
"tree-item-expanded": node.expanded,
|
|
42
|
+
"tree-item-open": !node.expanded
|
|
43
|
+
}),
|
|
44
|
+
onClick: (e)=>onSelect(e, node),
|
|
45
|
+
style: {
|
|
46
|
+
left: `${left}px`,
|
|
47
|
+
width: `calc(100% - ${left}px)`
|
|
48
|
+
},
|
|
49
|
+
children: [
|
|
50
|
+
!node.folder && getFileIcon(node.label),
|
|
51
|
+
/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("span", {
|
|
52
|
+
className: "label-name",
|
|
53
|
+
children: node.label
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
}, __WEBPACK_EXTERNAL_MODULE_react_window__.areEqual);
|
|
59
|
+
const getItemData = (0, __WEBPACK_EXTERNAL_MODULE_memoize_one__["default"])((onOpen, onSelect, flattenedData, selectedKeys)=>({
|
|
60
|
+
onOpen,
|
|
61
|
+
onSelect,
|
|
62
|
+
flattenedData,
|
|
63
|
+
selectedKeys
|
|
64
|
+
}));
|
|
65
|
+
const FileTree = (props)=>{
|
|
66
|
+
const { modules, selectedKeys = [] } = props;
|
|
67
|
+
const [openedNodeIds, setOpenedNodeIds] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)([]);
|
|
68
|
+
const onOpen = (node)=>{
|
|
69
|
+
if (!node.folder) return;
|
|
70
|
+
node.expanded ? setOpenedNodeIds(openedNodeIds.filter((id)=>id !== node.id)) : setOpenedNodeIds([
|
|
71
|
+
...openedNodeIds,
|
|
72
|
+
node.id
|
|
73
|
+
]);
|
|
74
|
+
};
|
|
75
|
+
const onSelect = (e, node)=>{
|
|
76
|
+
//e.stopPropagation();
|
|
77
|
+
if (node.folder) return;
|
|
78
|
+
console.log("---node", e, node);
|
|
79
|
+
props.onSelect?.(node.id);
|
|
80
|
+
};
|
|
81
|
+
const flattenedData = createFlattenTree(modules, openedNodeIds);
|
|
82
|
+
const itemData = getItemData(onOpen, onSelect, flattenedData, selectedKeys);
|
|
83
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_react_virtualized_auto_sizer__["default"], {
|
|
84
|
+
children: ({ height, width })=>/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_react_window__.FixedSizeList, {
|
|
85
|
+
className: "code-file-tree",
|
|
86
|
+
height: height,
|
|
87
|
+
itemCount: flattenedData.length,
|
|
88
|
+
itemSize: 22,
|
|
89
|
+
width: width,
|
|
90
|
+
itemKey: (index)=>flattenedData[index].id,
|
|
91
|
+
itemData: itemData,
|
|
92
|
+
children: Row
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
function createFlattenTree(data, expandedKeys) {
|
|
97
|
+
const flatTree = [];
|
|
98
|
+
const filePaths = Object.keys(data);
|
|
99
|
+
// console.log(JSON.parse(JSON.stringify(filePaths)))
|
|
100
|
+
// filePaths.sort((a, b) => {
|
|
101
|
+
// // 检查字符串a是否包含斜杠
|
|
102
|
+
// const hasSlashA = a.substring(1).lastIndexOf('/');
|
|
103
|
+
// // 检查字符串b是否包含斜杠
|
|
104
|
+
// const hasSlashB = b.substring(1).lastIndexOf('/');
|
|
105
|
+
// console.log('---a', hasSlashA)
|
|
106
|
+
// console.log('---b', hasSlashB)
|
|
107
|
+
// // 如果a包含斜杠,而b不包含,则a应该排在b之后
|
|
108
|
+
// if (hasSlashA > -1 && hasSlashB > -1) {
|
|
109
|
+
// return hasSlashB - hasSlashA;
|
|
110
|
+
// }
|
|
111
|
+
// return naturalCompare(a, b, {
|
|
112
|
+
// caseInsensitive: true,
|
|
113
|
+
// }); // 包含斜杠的字符串按字典顺序排序
|
|
114
|
+
// });
|
|
115
|
+
// console.log(filePaths)
|
|
116
|
+
filePaths.forEach((key)=>{
|
|
117
|
+
const parts = key.split("/");
|
|
118
|
+
const fileNames = [];
|
|
119
|
+
for(let i = 1; i <= parts.length; i++){
|
|
120
|
+
const path = parts.slice(0, i).join("/");
|
|
121
|
+
let expanded = expandedKeys.includes(path);
|
|
122
|
+
if (path && !flatTree.some((node)=>node.id === path)) fileNames.push({
|
|
123
|
+
id: path,
|
|
124
|
+
label: parts[i - 1] || "/",
|
|
125
|
+
folder: i < parts.length,
|
|
126
|
+
depth: i - 1,
|
|
127
|
+
expanded: expanded
|
|
128
|
+
});
|
|
129
|
+
if (expanded) break;
|
|
130
|
+
}
|
|
131
|
+
// console.log('--fileNames', fileNames);
|
|
132
|
+
fileNames.sort((a, b)=>(0, __WEBPACK_EXTERNAL_MODULE_string_natural_compare__["default"])(a.id, b.id, {
|
|
133
|
+
caseInsensitive: true
|
|
134
|
+
}));
|
|
135
|
+
flatTree.push(...fileNames);
|
|
136
|
+
});
|
|
137
|
+
return flatTree;
|
|
138
|
+
}
|
|
139
|
+
export { FileTree, createFlattenTree };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: file-types-iconfont;
|
|
3
|
+
src: url("//at.alicdn.com/t/c/font_4778352_pnoedg9yxml.woff2?t=1733906731817") format("woff2"), url("//at.alicdn.com/t/c/font_4778352_pnoedg9yxml.woff?t=1733906731817") format("woff"), url("//at.alicdn.com/t/c/font_4778352_pnoedg9yxml.ttf?t=1733906731817") format("truetype");
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.file-types-iconfont {
|
|
7
|
+
-webkit-font-smoothing: antialiased;
|
|
8
|
+
-moz-osx-font-smoothing: grayscale;
|
|
9
|
+
font-size: 14px;
|
|
10
|
+
font-style: normal;
|
|
11
|
+
font-family: file-types-iconfont !important;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.file-types-icon-git:before {
|
|
15
|
+
content: "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.file-types-icon-html:before {
|
|
19
|
+
content: "";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.file-types-icon-tsconfig:before {
|
|
23
|
+
content: "";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.file-types-icon-less:before {
|
|
27
|
+
content: "";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.file-types-icon-scss:before {
|
|
31
|
+
content: "";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.file-types-icon-json:before {
|
|
35
|
+
content: "";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.file-types-icon-css:before {
|
|
39
|
+
content: "";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.file-types-icon-text:before {
|
|
43
|
+
content: "";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.file-types-icon-js:before {
|
|
47
|
+
content: "";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.file-types-icon-jsx:before {
|
|
51
|
+
content: "";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.file-types-icon-ts:before {
|
|
55
|
+
content: "";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.file-types-icon-tsx:before {
|
|
59
|
+
content: "";
|
|
60
|
+
}
|
|
61
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import './index.less';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export type FileTypeIconProps = React.HtmlHTMLAttributes<HTMLSpanElement> & {
|
|
4
|
+
type: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function FileTypeIcon({ type, ...props }: FileTypeIconProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__ from "react/jsx-runtime";
|
|
2
|
+
import "./index.css";
|
|
3
|
+
import "react";
|
|
4
|
+
function FileTypeIcon({ type, ...props }) {
|
|
5
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("i", {
|
|
6
|
+
...props,
|
|
7
|
+
className: `file-types-iconfont file-types-icon-${type} ${props.className || ''}`
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export { FileTypeIcon };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "@gant-lowcode/lowcode-plugin-base-monaco-editor/lib/style";
|
|
2
|
+
import { GravityCode } from "../../types";
|
|
3
|
+
import "./index.less";
|
|
4
|
+
export declare function SourcesView({ code, onCodeChange, }: {
|
|
5
|
+
code: GravityCode;
|
|
6
|
+
onCodeChange: (code: GravityCode) => void;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__ from "react/jsx-runtime";
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
|
|
3
|
+
import * as __WEBPACK_EXTERNAL_MODULE_antd__ from "antd";
|
|
4
|
+
import * as __WEBPACK_EXTERNAL_MODULE__gant_lowcode_lowcode_plugin_base_monaco_editor__ from "@gant-lowcode/lowcode-plugin-base-monaco-editor";
|
|
5
|
+
import "@gant-lowcode/lowcode-plugin-base-monaco-editor/lib/style";
|
|
6
|
+
import * as __WEBPACK_EXTERNAL_MODULE__file_tree_index_js__ from "../file-tree/index.js";
|
|
7
|
+
import "./index.css";
|
|
8
|
+
const DEBOUNCE_UPDATE_INTERVAL_IN_MS = 500;
|
|
9
|
+
function SourcesView({ code, onCodeChange }) {
|
|
10
|
+
const editorContainerRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
11
|
+
const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(()=>{
|
|
12
|
+
const allFiles = Object.values(code.modules);
|
|
13
|
+
const currentFile = [
|
|
14
|
+
allFiles.find((x)=>/pages.+(js|ts)x?$/.test(x.fpath)),
|
|
15
|
+
allFiles.find((m)=>m.entry)
|
|
16
|
+
].filter(Boolean)[0];
|
|
17
|
+
return {
|
|
18
|
+
currentFile,
|
|
19
|
+
selectedKeys: [
|
|
20
|
+
currentFile?.fpath
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
const [height, setHeight] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(0);
|
|
25
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(()=>{
|
|
26
|
+
const observer = new ResizeObserver(()=>{
|
|
27
|
+
if (editorContainerRef.current) {
|
|
28
|
+
const { height } = editorContainerRef.current.getBoundingClientRect();
|
|
29
|
+
setHeight(height - 2);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (editorContainerRef.current) observer.observe(editorContainerRef.current);
|
|
33
|
+
return ()=>{
|
|
34
|
+
if (editorContainerRef.current) observer.unobserve(editorContainerRef.current);
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
const ref = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)({
|
|
38
|
+
debounceTimer: null
|
|
39
|
+
});
|
|
40
|
+
const onSelect = (key)=>{
|
|
41
|
+
setState((prev)=>{
|
|
42
|
+
if (ref.current.debounceTimer) ref.current.debounceTimer = null;
|
|
43
|
+
return {
|
|
44
|
+
...prev,
|
|
45
|
+
currentFile: code.modules[key] || prev.currentFile
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsxs)(__WEBPACK_EXTERNAL_MODULE_antd__.Splitter, {
|
|
50
|
+
className: "sources-panes",
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_antd__.Splitter.Panel, {
|
|
53
|
+
defaultSize: 300,
|
|
54
|
+
min: 300,
|
|
55
|
+
max: "70%",
|
|
56
|
+
className: "file-tree-pane",
|
|
57
|
+
children: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE__file_tree_index_js__.FileTree, {
|
|
58
|
+
modules: code.modules,
|
|
59
|
+
onSelect: onSelect,
|
|
60
|
+
selectedKeys: state.currentFile?.fpath ? [
|
|
61
|
+
state.currentFile?.fpath
|
|
62
|
+
] : void 0
|
|
63
|
+
})
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE_antd__.Splitter.Panel, {
|
|
66
|
+
className: "source-code-pane",
|
|
67
|
+
children: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)("div", {
|
|
68
|
+
ref: editorContainerRef,
|
|
69
|
+
style: {
|
|
70
|
+
height: "100%"
|
|
71
|
+
},
|
|
72
|
+
children: /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime__.jsx)(__WEBPACK_EXTERNAL_MODULE__gant_lowcode_lowcode_plugin_base_monaco_editor__["default"], {
|
|
73
|
+
height: height,
|
|
74
|
+
language: getFileLanguage(state.currentFile?.fpath),
|
|
75
|
+
saveViewState: true,
|
|
76
|
+
defaultValue: state.currentFile?.code,
|
|
77
|
+
path: state.currentFile?.fpath,
|
|
78
|
+
onChange: (value)=>{
|
|
79
|
+
console.debug("[monaco editor] onChange: %o (currentFile: %o)", {
|
|
80
|
+
value
|
|
81
|
+
}, state.currentFile);
|
|
82
|
+
const currentFile = state.currentFile;
|
|
83
|
+
if (currentFile) {
|
|
84
|
+
if (ref.current.debounceTimer) clearTimeout(ref.current.debounceTimer);
|
|
85
|
+
ref.current.debounceTimer = setTimeout(()=>{
|
|
86
|
+
ref.current.debounceTimer = null;
|
|
87
|
+
onCodeChange({
|
|
88
|
+
...code,
|
|
89
|
+
modules: {
|
|
90
|
+
...code.modules,
|
|
91
|
+
[currentFile.fpath]: {
|
|
92
|
+
...currentFile,
|
|
93
|
+
code: value || ""
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}, DEBOUNCE_UPDATE_INTERVAL_IN_MS);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function getFileLanguage(file) {
|
|
107
|
+
switch((file || "").split(".").pop()){
|
|
108
|
+
case "ts":
|
|
109
|
+
case "tsx":
|
|
110
|
+
return "typescript";
|
|
111
|
+
case "js":
|
|
112
|
+
case "jsx":
|
|
113
|
+
return "javascript";
|
|
114
|
+
case "css":
|
|
115
|
+
return "css";
|
|
116
|
+
case "scss":
|
|
117
|
+
return "scss";
|
|
118
|
+
case "less":
|
|
119
|
+
return "less";
|
|
120
|
+
case "json":
|
|
121
|
+
return "json";
|
|
122
|
+
case "md":
|
|
123
|
+
return "markdown";
|
|
124
|
+
default:
|
|
125
|
+
return "text";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export { SourcesView };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { IPublicModelPluginContext } from "@gant-lowcode/lowcode-types";
|
|
2
|
+
import * as CodeGenerator from "@gant-lowcode/code-generator/standalone-loader";
|
|
3
|
+
export type CodeGenPluginOptions = {
|
|
4
|
+
/** 是否要禁用出码的动作按钮(默认: 否) */
|
|
5
|
+
disableCodeGenActionBtn?: boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const plugin: {
|
|
8
|
+
(ctx: IPublicModelPluginContext, options?: CodeGenPluginOptions): {
|
|
9
|
+
exports(): {
|
|
10
|
+
generateCode: typeof CodeGenerator.generateCode;
|
|
11
|
+
};
|
|
12
|
+
init(): Promise<void>;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
};
|
|
15
|
+
pluginName: string;
|
|
16
|
+
meta: {
|
|
17
|
+
dependencies: never[];
|
|
18
|
+
preferenceDeclaration: {
|
|
19
|
+
title: string;
|
|
20
|
+
properties: {
|
|
21
|
+
key: string;
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export default plugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE__gant_lowcode_code_generator_standalone_loader__ from "@gant-lowcode/code-generator/standalone-loader";
|
|
2
|
+
import * as __WEBPACK_EXTERNAL_MODULE__components_code_gen_action_index_js__ from "./components/code-gen-action/index.js";
|
|
3
|
+
const src_rslib_entry_plugin = (ctx, options)=>({
|
|
4
|
+
// 插件对外暴露的数据和方法
|
|
5
|
+
exports () {
|
|
6
|
+
return {
|
|
7
|
+
generateCode: __WEBPACK_EXTERNAL_MODULE__gant_lowcode_code_generator_standalone_loader__.generateCode
|
|
8
|
+
};
|
|
9
|
+
},
|
|
10
|
+
// 插件的初始化函数,在引擎初始化之后会立刻调用
|
|
11
|
+
async init () {
|
|
12
|
+
try {
|
|
13
|
+
if (!options?.disableCodeGenActionBtn) ctx.skeleton.add({
|
|
14
|
+
type: "Custom",
|
|
15
|
+
name: "code-generator",
|
|
16
|
+
area: "topArea",
|
|
17
|
+
props: {
|
|
18
|
+
align: "right",
|
|
19
|
+
width: 100
|
|
20
|
+
},
|
|
21
|
+
content: __WEBPACK_EXTERNAL_MODULE__components_code_gen_action_index_js__.CodeGenActionBtn,
|
|
22
|
+
contentProps: {
|
|
23
|
+
ctx
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
// 提前初始化下,这样后面用的时候更快
|
|
27
|
+
__WEBPACK_EXTERNAL_MODULE__gant_lowcode_code_generator_standalone_loader__.init();
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error("[plugin-code-geneator] failed to init: ", e);
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
destroy () {}
|
|
34
|
+
});
|
|
35
|
+
src_rslib_entry_plugin.pluginName = "codeGenerator";
|
|
36
|
+
src_rslib_entry_plugin.meta = {
|
|
37
|
+
dependencies: [],
|
|
38
|
+
preferenceDeclaration: {
|
|
39
|
+
title: "codeGenerator 的参数定义",
|
|
40
|
+
properties: [
|
|
41
|
+
{
|
|
42
|
+
key: "disableCodeGenActionBtn",
|
|
43
|
+
type: "boolean",
|
|
44
|
+
description: "是否要禁用出码的动作按钮"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/* ESM default export */ const src_rslib_entry_ = src_rslib_entry_plugin;
|
|
50
|
+
export { src_rslib_entry_ as default };
|