@blocklet/pages-kit-block-studio 0.0.18 → 0.1.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/lib/cjs/constants/index.js +12 -1
- package/lib/cjs/constants/new-block-template/@metadata.json +59 -0
- package/lib/cjs/constants/new-block-template/index.js +55 -0
- package/lib/cjs/constants/new-block-template/index.tsx +89 -0
- package/lib/cjs/middlewares/init-block-studio-router.js +43 -9
- package/lib/cjs/middlewares/init-resource-router.js +5 -1
- package/lib/cjs/plugins/vite-plugin-block-studio.js +29 -31
- package/lib/cjs/plugins/vite-plugin-html-transform.js +40 -5
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/generate-wrapper-code.js +21 -25
- package/lib/cjs/utils/helper.js +20 -12
- package/lib/esm/constants/index.js +8 -0
- package/lib/esm/constants/new-block-template/@metadata.json +59 -0
- package/lib/esm/constants/new-block-template/index.js +50 -0
- package/lib/esm/constants/new-block-template/index.tsx +89 -0
- package/lib/esm/middlewares/init-block-studio-router.js +44 -10
- package/lib/esm/middlewares/init-resource-router.js +5 -1
- package/lib/esm/plugins/vite-plugin-block-studio.js +29 -31
- package/lib/esm/plugins/vite-plugin-html-transform.js +40 -5
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/generate-wrapper-code.js +21 -25
- package/lib/esm/utils/helper.js +10 -6
- package/lib/types/constants/index.d.ts +7 -0
- package/lib/types/constants/new-block-template/index.d.ts +13 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/helper.d.ts +2 -4
- package/package.json +17 -5
- package/tsconfig.json +3 -1
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MEDIA_KIT_RESOURCE_TYPE = exports.MEDIA_KIT_DID = exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = exports.PAGES_KIT_BLOCK_STUDIO_DID = exports.PAGES_KIT_RESOURCE_TYPE = exports.PAGES_KIT_DID = void 0;
|
|
6
|
+
exports.DEFAULT_BLOCK_ENTRY_FILES_PATTERN = exports.NANOID_LENGTH = exports.PREVIEW_IMAGE_DIR = exports.METADATA_FILE_NAME = exports.libDir = exports.NEW_BLOCK_TEMPLATE_METADATA_PATH = exports.NEW_BLOCK_TEMPLATE_PATH = exports.MEDIA_KIT_RESOURCE_TYPE = exports.MEDIA_KIT_DID = exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = exports.PAGES_KIT_BLOCK_STUDIO_DID = exports.PAGES_KIT_RESOURCE_TYPE = exports.PAGES_KIT_DID = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
4
8
|
exports.PAGES_KIT_DID = 'z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o';
|
|
5
9
|
exports.PAGES_KIT_RESOURCE_TYPE = 'page';
|
|
6
10
|
exports.PAGES_KIT_BLOCK_STUDIO_DID = 'z2qa7rr3eUyVnWp2PCxEVARuUfLFh6cE5V2xV';
|
|
7
11
|
exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = 'page';
|
|
8
12
|
exports.MEDIA_KIT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9';
|
|
9
13
|
exports.MEDIA_KIT_RESOURCE_TYPE = 'imgpack';
|
|
14
|
+
exports.NEW_BLOCK_TEMPLATE_PATH = path_1.default.join(__dirname, 'new-block-template', 'index.tsx');
|
|
15
|
+
exports.NEW_BLOCK_TEMPLATE_METADATA_PATH = path_1.default.join(__dirname, 'new-block-template', '@metadata.json');
|
|
16
|
+
exports.libDir = 'lib';
|
|
17
|
+
exports.METADATA_FILE_NAME = '@metadata.json';
|
|
18
|
+
exports.PREVIEW_IMAGE_DIR = '@preview-images';
|
|
19
|
+
exports.NANOID_LENGTH = 16;
|
|
20
|
+
exports.DEFAULT_BLOCK_ENTRY_FILES_PATTERN = 'src/**/index.{ts,tsx,html}';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"properties": {
|
|
3
|
+
"gs1rn5jmxfvpxptx": {
|
|
4
|
+
"index": 0,
|
|
5
|
+
"data": {
|
|
6
|
+
"id": "gs1rn5jmxfvpxptx",
|
|
7
|
+
"key": "title",
|
|
8
|
+
"locales": {
|
|
9
|
+
"zh": {
|
|
10
|
+
"name": "Title"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"9ajrz12ik7esfk1z": {
|
|
16
|
+
"index": 1,
|
|
17
|
+
"data": {
|
|
18
|
+
"id": "9ajrz12ik7esfk1z",
|
|
19
|
+
"key": "description",
|
|
20
|
+
"locales": {
|
|
21
|
+
"zh": {
|
|
22
|
+
"name": "Description",
|
|
23
|
+
"defaultValue": "Welcome to Pages Kit Block Studio"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"3ckcfvf6b7zyskk8": {
|
|
29
|
+
"index": 2,
|
|
30
|
+
"data": {
|
|
31
|
+
"id": "3ckcfvf6b7zyskk8",
|
|
32
|
+
"key": "logo",
|
|
33
|
+
"type": "url",
|
|
34
|
+
"locales": {
|
|
35
|
+
"zh": {
|
|
36
|
+
"defaultValue": {
|
|
37
|
+
"url": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80",
|
|
38
|
+
"mediaKitUrl": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80"
|
|
39
|
+
},
|
|
40
|
+
"name": "Logo"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"x3lqht8ikble1itx": {
|
|
46
|
+
"index": 3,
|
|
47
|
+
"data": {
|
|
48
|
+
"id": "x3lqht8ikble1itx",
|
|
49
|
+
"key": "copyright",
|
|
50
|
+
"locales": {
|
|
51
|
+
"zh": {
|
|
52
|
+
"defaultValue": "Powered by Pages Kit Block Studio"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"visible": false
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.EditComponent = void 0;
|
|
15
|
+
exports.default = HelloWorld;
|
|
16
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
17
|
+
// default export
|
|
18
|
+
function HelloWorld({ title = 'Hello World', logo, description, copyright }) {
|
|
19
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
20
|
+
display: 'flex',
|
|
21
|
+
flexDirection: 'column',
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
padding: '16px 0',
|
|
24
|
+
}, children: [title && (0, jsx_runtime_1.jsx)("h1", { children: title }), logo && ((0, jsx_runtime_1.jsx)("img", { src: typeof logo === 'object' ? logo.url : logo, alt: "logo", style: {
|
|
25
|
+
margin: '16px 0',
|
|
26
|
+
maxWidth: '200px',
|
|
27
|
+
} })), description && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
28
|
+
color: '#666',
|
|
29
|
+
marginTop: '8px',
|
|
30
|
+
}, children: description })), copyright && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
31
|
+
color: '#999',
|
|
32
|
+
fontSize: '12px',
|
|
33
|
+
marginTop: '16px',
|
|
34
|
+
}, children: copyright }))] }));
|
|
35
|
+
}
|
|
36
|
+
// export edit component
|
|
37
|
+
const EditComponent = (_a) => {
|
|
38
|
+
var { onChange } = _a, props = __rest(_a, ["onChange"]);
|
|
39
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
|
|
40
|
+
fontSize: '14px',
|
|
41
|
+
fontWeight: 500,
|
|
42
|
+
color: '#333',
|
|
43
|
+
padding: '8px 0',
|
|
44
|
+
borderBottom: '1px solid #eee',
|
|
45
|
+
}, children: "Footer Parameters" }), (0, jsx_runtime_1.jsx)("input", { id: "copyright-input", type: "text", style: {
|
|
46
|
+
width: '100%',
|
|
47
|
+
padding: '8px 12px',
|
|
48
|
+
border: '1px solid #ddd',
|
|
49
|
+
borderRadius: '4px',
|
|
50
|
+
fontSize: '14px',
|
|
51
|
+
transition: 'border-color 0.3s',
|
|
52
|
+
outline: 'none',
|
|
53
|
+
}, value: props.copyright || '', onChange: (e) => onChange === null || onChange === void 0 ? void 0 : onChange({ copyright: e.target.value }), placeholder: "Please Input Copyright" })] }));
|
|
54
|
+
};
|
|
55
|
+
exports.EditComponent = EditComponent;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface HelloWorldProps {
|
|
4
|
+
title?: string;
|
|
5
|
+
logo?: string | { url: string };
|
|
6
|
+
description?: string;
|
|
7
|
+
copyright?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// default export
|
|
11
|
+
export default function HelloWorld({ title = 'Hello World', logo, description, copyright }: HelloWorldProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
style={{
|
|
15
|
+
display: 'flex',
|
|
16
|
+
flexDirection: 'column',
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
padding: '16px 0',
|
|
19
|
+
}}>
|
|
20
|
+
{title && <h1>{title}</h1>}
|
|
21
|
+
{logo && (
|
|
22
|
+
<img
|
|
23
|
+
src={typeof logo === 'object' ? logo.url : logo}
|
|
24
|
+
alt="logo"
|
|
25
|
+
style={{
|
|
26
|
+
margin: '16px 0',
|
|
27
|
+
maxWidth: '200px',
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
)}
|
|
31
|
+
{description && (
|
|
32
|
+
<div
|
|
33
|
+
style={{
|
|
34
|
+
color: '#666',
|
|
35
|
+
marginTop: '8px',
|
|
36
|
+
}}>
|
|
37
|
+
{description}
|
|
38
|
+
</div>
|
|
39
|
+
)}
|
|
40
|
+
{copyright && (
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
color: '#999',
|
|
44
|
+
fontSize: '12px',
|
|
45
|
+
marginTop: '16px',
|
|
46
|
+
}}>
|
|
47
|
+
{copyright}
|
|
48
|
+
</div>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// export edit component
|
|
55
|
+
export const EditComponent: React.FC<HelloWorldProps & { onChange?: (value: HelloWorldProps) => void }> = ({
|
|
56
|
+
onChange,
|
|
57
|
+
...props
|
|
58
|
+
}) => {
|
|
59
|
+
return (
|
|
60
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
61
|
+
<div
|
|
62
|
+
style={{
|
|
63
|
+
fontSize: '14px',
|
|
64
|
+
fontWeight: 500,
|
|
65
|
+
color: '#333',
|
|
66
|
+
padding: '8px 0',
|
|
67
|
+
borderBottom: '1px solid #eee',
|
|
68
|
+
}}>
|
|
69
|
+
Footer Parameters
|
|
70
|
+
</div>
|
|
71
|
+
<input
|
|
72
|
+
id="copyright-input"
|
|
73
|
+
type="text"
|
|
74
|
+
style={{
|
|
75
|
+
width: '100%',
|
|
76
|
+
padding: '8px 12px',
|
|
77
|
+
border: '1px solid #ddd',
|
|
78
|
+
borderRadius: '4px',
|
|
79
|
+
fontSize: '14px',
|
|
80
|
+
transition: 'border-color 0.3s',
|
|
81
|
+
outline: 'none',
|
|
82
|
+
}}
|
|
83
|
+
value={props.copyright || ''}
|
|
84
|
+
onChange={(e) => onChange?.({ copyright: e.target.value })}
|
|
85
|
+
placeholder="Please Input Copyright"
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
@@ -17,6 +17,7 @@ const express_1 = require("express");
|
|
|
17
17
|
const fs_1 = __importDefault(require("fs"));
|
|
18
18
|
const lodash_1 = require("lodash");
|
|
19
19
|
const path_1 = __importDefault(require("path"));
|
|
20
|
+
const constants_1 = require("../constants");
|
|
20
21
|
const helper_1 = require("../utils/helper");
|
|
21
22
|
exports.initBlockStudioRouter = (0, express_1.Router)();
|
|
22
23
|
const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.svg'];
|
|
@@ -43,11 +44,6 @@ exports.initBlockStudioRouter.get('/', (req, res) => __awaiter(void 0, void 0, v
|
|
|
43
44
|
return fs_1.default.createReadStream(filePath).pipe(res);
|
|
44
45
|
}
|
|
45
46
|
const metadata = (0, helper_1.initializeMetadata)(filePath);
|
|
46
|
-
const code = (0, helper_1.getBlockCode)(filePath);
|
|
47
|
-
if (code) {
|
|
48
|
-
(0, lodash_1.set)(metadata, 'renderer.script', code);
|
|
49
|
-
(0, lodash_1.set)(metadata, 'renderer.type', 'react-component');
|
|
50
|
-
}
|
|
51
47
|
return res.json(metadata);
|
|
52
48
|
}
|
|
53
49
|
catch (error) {
|
|
@@ -87,16 +83,54 @@ exports.initBlockStudioRouter.post('/', (req, res) => __awaiter(void 0, void 0,
|
|
|
87
83
|
});
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
|
-
res.json({ success: true, content: mergedContent, message: 'Updated' });
|
|
91
|
-
// save metadata without renderer after response
|
|
92
|
-
delete mergedContent.renderer;
|
|
93
86
|
fs_1.default.writeFileSync(filePath, JSON.stringify(mergedContent, null, 2));
|
|
94
|
-
return
|
|
87
|
+
return res.json({ success: true, content: mergedContent, message: 'Updated' });
|
|
95
88
|
}
|
|
96
89
|
catch (error) {
|
|
97
90
|
return res.status(500).json({ error: 'Failed to write file' });
|
|
98
91
|
}
|
|
99
92
|
}));
|
|
93
|
+
exports.initBlockStudioRouter.post('/create', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
|
+
if (!helper_1.isDev) {
|
|
95
|
+
return res.status(403).json({ error: 'Only available in development mode' });
|
|
96
|
+
}
|
|
97
|
+
const { name, description } = req.body;
|
|
98
|
+
if (!name) {
|
|
99
|
+
return res.status(400).json({ error: 'Name is required' });
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const pattern = (0, helper_1.getBlockEntryFilesPattern)();
|
|
103
|
+
const baseDir = path_1.default.dirname(pattern.replace(/\*\*?/g, ''));
|
|
104
|
+
const blockDir = path_1.default.join(baseDir, name);
|
|
105
|
+
const metadataPath = path_1.default.join(blockDir, constants_1.METADATA_FILE_NAME);
|
|
106
|
+
const indexPath = path_1.default.join(blockDir, 'index.tsx');
|
|
107
|
+
// Check if block already exists
|
|
108
|
+
if (fs_1.default.existsSync(blockDir)) {
|
|
109
|
+
return res.status(409).json({ error: 'Block already exists' });
|
|
110
|
+
}
|
|
111
|
+
// Create block directory
|
|
112
|
+
fs_1.default.mkdirSync(blockDir, { recursive: true });
|
|
113
|
+
// Initialize metadata
|
|
114
|
+
let metadata = (0, helper_1.initializeMetadata)(metadataPath);
|
|
115
|
+
metadata.name = name;
|
|
116
|
+
metadata.description = description || '';
|
|
117
|
+
metadata.createdAt = new Date().toISOString();
|
|
118
|
+
metadata.updatedAt = new Date().toISOString();
|
|
119
|
+
// get template metadata from @metadata.json
|
|
120
|
+
const metadataContent = fs_1.default.readFileSync(constants_1.NEW_BLOCK_TEMPLATE_METADATA_PATH, 'utf-8');
|
|
121
|
+
metadata = Object.assign(Object.assign({}, metadata), (0, helper_1.safeParse)(metadataContent));
|
|
122
|
+
// Write metadata file
|
|
123
|
+
fs_1.default.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
|
|
124
|
+
// Copy template file to index.tsx
|
|
125
|
+
const templateContent = fs_1.default.readFileSync(constants_1.NEW_BLOCK_TEMPLATE_PATH, 'utf-8');
|
|
126
|
+
fs_1.default.writeFileSync(indexPath, templateContent);
|
|
127
|
+
return res.json({ success: true, metadata });
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error('Failed to create block:', error);
|
|
131
|
+
return res.status(500).json({ error: 'Failed to create block' });
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
100
134
|
exports.initBlockStudioRouter.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
135
|
const { withBlockletData = true } = req.query;
|
|
102
136
|
const allBlocks = yield (0, helper_1.findComponentFiles)();
|
|
@@ -140,7 +140,7 @@ exports.initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, voi
|
|
|
140
140
|
const buildProcess = (0, child_process_1.spawn)('pnpm', ['run', 'build-lib'], {
|
|
141
141
|
stdio: 'inherit',
|
|
142
142
|
shell: true,
|
|
143
|
-
env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(',') }),
|
|
143
|
+
env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(','), NODE_OPTIONS: '--max_old_space_size=16384' }),
|
|
144
144
|
});
|
|
145
145
|
yield new Promise((resolve, reject) => {
|
|
146
146
|
buildProcess.on('close', (code) => {
|
|
@@ -149,6 +149,10 @@ exports.initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, voi
|
|
|
149
149
|
else
|
|
150
150
|
reject(new Error(`Build process exited with code ${code}`));
|
|
151
151
|
});
|
|
152
|
+
buildProcess.on('error', (error) => {
|
|
153
|
+
console.error('Build process error:', error);
|
|
154
|
+
reject(error);
|
|
155
|
+
});
|
|
152
156
|
});
|
|
153
157
|
const dir = getExportDir(projectId, releaseId);
|
|
154
158
|
fs_1.default.rmSync(dir, { recursive: true, force: true });
|
|
@@ -47,6 +47,7 @@ exports.initBlockStudioPlugins = initBlockStudioPlugins;
|
|
|
47
47
|
// import typescript from '@rollup/plugin-typescript';
|
|
48
48
|
const fs_1 = require("fs");
|
|
49
49
|
const path = __importStar(require("path"));
|
|
50
|
+
const ufo_1 = require("ufo");
|
|
50
51
|
const vite_plugin_react_pages_1 = __importStar(require("vite-plugin-react-pages"));
|
|
51
52
|
const helper_1 = require("../utils/helper");
|
|
52
53
|
const vite_plugin_html_transform_1 = require("./vite-plugin-html-transform");
|
|
@@ -108,18 +109,13 @@ function initBlockStudioPlugins(options) {
|
|
|
108
109
|
formats: ['es', !multiMode ? 'umd' : 'cjs'],
|
|
109
110
|
fileName: (format, entryName) => `${format}/${entryName}.js`,
|
|
110
111
|
}, rollupOptions: {
|
|
111
|
-
external:
|
|
112
|
-
'react',
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// '@emotion/react',
|
|
119
|
-
// '@emotion/styled',
|
|
120
|
-
'@arcblock/ux',
|
|
121
|
-
'@arcblock/did-connect',
|
|
122
|
-
],
|
|
112
|
+
external: (id) => {
|
|
113
|
+
const skip = ['react', 'crypto'];
|
|
114
|
+
if (skip.some((s) => id === s)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
},
|
|
123
119
|
output: {
|
|
124
120
|
chunkFileNames: () => {
|
|
125
121
|
return '[format]/_chunks/[name]-[hash].js';
|
|
@@ -127,22 +123,13 @@ function initBlockStudioPlugins(options) {
|
|
|
127
123
|
// 为所有外部依赖提供全局变量
|
|
128
124
|
globals: {
|
|
129
125
|
react: 'React',
|
|
130
|
-
'react-dom': 'ReactDOM',
|
|
131
|
-
'react-is': 'ReactIs',
|
|
132
|
-
'react-router-dom': 'ReactRouterDOM',
|
|
133
|
-
'react/jsx-runtime': 'ReactJsxRuntime',
|
|
134
|
-
// '@emotion/react': 'emotionReact',
|
|
135
|
-
// '@emotion/styled': 'emotionStyled',
|
|
136
|
-
'@mui/material': 'MUI',
|
|
137
|
-
'@arcblock/ux': 'ArcBlockUX',
|
|
138
|
-
'@arcblock/did-connect': 'ArcBlockDidConnect',
|
|
139
126
|
},
|
|
140
127
|
paths: {
|
|
141
|
-
|
|
142
|
-
|
|
128
|
+
// Redirect 'react' imports to '@blocklet/pages-kit/builtin/react'
|
|
129
|
+
react: '@blocklet/pages-kit/builtin/react',
|
|
143
130
|
},
|
|
144
131
|
// 确保正确处理命名导出和默认导出
|
|
145
|
-
|
|
132
|
+
interop: 'auto',
|
|
146
133
|
},
|
|
147
134
|
} }, _config === null || _config === void 0 ? void 0 : _config.build),
|
|
148
135
|
};
|
|
@@ -162,21 +149,23 @@ function initBlockStudioPlugins(options) {
|
|
|
162
149
|
const pageId = `/${blockName}`;
|
|
163
150
|
const dirPath = path.dirname(filePath);
|
|
164
151
|
const metadataPath = path.join(dirPath, '@metadata.json');
|
|
152
|
+
const dataPath = isHtml ? `${vite_plugin_html_transform_1.VIRTUAL_MODULE_ID}?dir=${dirPath}` : filePath;
|
|
165
153
|
api.addPageData({
|
|
166
154
|
pageId,
|
|
167
|
-
dataPath
|
|
155
|
+
dataPath,
|
|
168
156
|
staticData: isHtml
|
|
169
157
|
? {
|
|
170
|
-
|
|
171
|
-
dataPath
|
|
172
|
-
code: (0, vite_plugin_html_transform_1.generateComponent)((0, vite_plugin_html_transform_1.readHtmlFiles)(dirPath
|
|
158
|
+
isHtml: true,
|
|
159
|
+
dataPath,
|
|
160
|
+
code: (0, vite_plugin_html_transform_1.generateComponent)((0, vite_plugin_html_transform_1.readHtmlFiles)(dirPath)),
|
|
173
161
|
blockName,
|
|
174
162
|
dirPath,
|
|
163
|
+
importPath: (0, ufo_1.joinURL)('@id', dataPath),
|
|
175
164
|
metadataPath,
|
|
176
165
|
}
|
|
177
|
-
: Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: (0, fs_1.readFileSync)(file.path, 'utf-8'), dataPath
|
|
178
|
-
|
|
179
|
-
metadataPath }),
|
|
166
|
+
: Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: (0, fs_1.readFileSync)(file.path, 'utf-8'), dataPath,
|
|
167
|
+
blockName,
|
|
168
|
+
dirPath, importPath: (0, ufo_1.joinURL)('@fs', dataPath), metadataPath }),
|
|
180
169
|
});
|
|
181
170
|
});
|
|
182
171
|
});
|
|
@@ -197,6 +186,15 @@ function initBlockStudioPlugins(options) {
|
|
|
197
186
|
// maxConcurrent: 5, // 可选,默认值
|
|
198
187
|
// timeout: 30 * 1000, // 可选,默认值 30 秒
|
|
199
188
|
// }),
|
|
189
|
+
{
|
|
190
|
+
name: 'build-force-exit',
|
|
191
|
+
apply: 'build',
|
|
192
|
+
enforce: 'post',
|
|
193
|
+
closeBundle() {
|
|
194
|
+
// ensure vite build exit
|
|
195
|
+
process.exit(0);
|
|
196
|
+
},
|
|
197
|
+
},
|
|
200
198
|
];
|
|
201
199
|
}
|
|
202
200
|
exports.default = initBlockStudioPlugins;
|
|
@@ -21,6 +21,7 @@ exports.RESOLVED_VIRTUAL_MODULE_ID = `\0${exports.VIRTUAL_MODULE_ID}`;
|
|
|
21
21
|
const isRelativePath = (path) => {
|
|
22
22
|
return path.startsWith('./') || path.startsWith('../') || (!path.startsWith('http') && !path.startsWith('//'));
|
|
23
23
|
};
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
24
25
|
function extractExternalResources(html, _dirPath) {
|
|
25
26
|
const external = {
|
|
26
27
|
js: [],
|
|
@@ -170,10 +171,24 @@ ${content.trim()}`;
|
|
|
170
171
|
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
|
171
172
|
<meta http-equiv="Referrer-Policy" content="no-referrer">
|
|
172
173
|
<meta http-equiv="Permissions-Policy" content="accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()">`;
|
|
174
|
+
const autoHeightScript = `<script>
|
|
175
|
+
(function() {
|
|
176
|
+
if ('ResizeObserver' in window) {
|
|
177
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
178
|
+
const height = document.documentElement.scrollHeight;
|
|
179
|
+
window.parent.postMessage({ height }, '*');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
resizeObserver.observe(document.documentElement);
|
|
183
|
+
}
|
|
184
|
+
})();
|
|
185
|
+
</script>`;
|
|
173
186
|
// 将处理后的相对路径引入的 CSS 和 JS 注入到 HTML 中
|
|
174
187
|
const htmlContent = htmlWithoutRelativeImport
|
|
175
188
|
.replace('<head>', `<head>${securityHeaders}`)
|
|
176
189
|
.replace('</head>', `${cssContents.map((css) => `<style>${css.trim()}</style>`).join('\n')}
|
|
190
|
+
|
|
191
|
+
${autoHeightScript}
|
|
177
192
|
</head>`)
|
|
178
193
|
.replace('</body>', `
|
|
179
194
|
${jsContents.map((js) => `<script>${js}</script>`).join('\n')}
|
|
@@ -190,21 +205,41 @@ ${content.trim()}`;
|
|
|
190
205
|
name: (0, path_1.basename)(dirPath),
|
|
191
206
|
};
|
|
192
207
|
}
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
193
209
|
function generateComponent(content, _isDev = true) {
|
|
194
210
|
const htmlContent = content.html;
|
|
195
211
|
const { name } = content;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
return `import { createElement } from 'react';
|
|
212
|
+
return `import { createElement, useEffect, useRef } from 'react';
|
|
213
|
+
|
|
200
214
|
|
|
201
215
|
export default function HtmlPreview() {
|
|
216
|
+
const iframeRef = useRef(null);
|
|
217
|
+
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
const iframe = iframeRef.current;
|
|
220
|
+
if (!iframe) return;
|
|
221
|
+
|
|
222
|
+
const handleMessage = (event) => {
|
|
223
|
+
if (event.source === iframe.contentWindow) {
|
|
224
|
+
const height = event.data.height;
|
|
225
|
+
if (height) {
|
|
226
|
+
iframe.style.height = height + 'px';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
window.addEventListener('message', handleMessage);
|
|
232
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
233
|
+
}, []);
|
|
234
|
+
|
|
202
235
|
return createElement('iframe', {
|
|
203
|
-
|
|
236
|
+
ref: iframeRef,
|
|
237
|
+
style: { border: 'none', width: '100%', height: '100%', maxHeight: '100vh' },
|
|
204
238
|
sandbox: 'allow-scripts',
|
|
205
239
|
title: 'Preview ${name}',
|
|
206
240
|
srcDoc: ${htmlContent}
|
|
207
241
|
});
|
|
242
|
+
|
|
208
243
|
}`;
|
|
209
244
|
}
|
|
210
245
|
function initHtmlPreviewTransformPlugin() {
|