@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
|
@@ -275,12 +275,10 @@ function getCustomComponentPropertyType(type) {
|
|
|
275
275
|
}
|
|
276
276
|
const ALLOWED_PROPERTY_TYPES = ['string', 'multiline', 'url', 'json', 'yaml'];
|
|
277
277
|
function generatePageDataTypes(state) {
|
|
278
|
-
const
|
|
278
|
+
const pageTypeDefinitions = Object.values(state.pages)
|
|
279
279
|
.map((page) => {
|
|
280
|
-
// check if the page is a template page
|
|
281
280
|
if (!page.isTemplate)
|
|
282
281
|
return null;
|
|
283
|
-
// 将 slug 转换为有效的 TypeScript 类型名
|
|
284
282
|
const typeName = `Page${page.slug
|
|
285
283
|
.replace(/^\//, '')
|
|
286
284
|
.split('/')
|
|
@@ -331,8 +329,7 @@ ${properties}
|
|
|
331
329
|
})
|
|
332
330
|
.filter(Boolean)
|
|
333
331
|
.join('\n');
|
|
334
|
-
|
|
335
|
-
export interface ${typeName} {
|
|
332
|
+
const typeDefinition = `interface ${typeName} {
|
|
336
333
|
title?: string;
|
|
337
334
|
image?: string;
|
|
338
335
|
description?: string;
|
|
@@ -340,29 +337,28 @@ export interface ${typeName} {
|
|
|
340
337
|
${sectionTypes}
|
|
341
338
|
};
|
|
342
339
|
}`;
|
|
340
|
+
return {
|
|
341
|
+
typeName,
|
|
342
|
+
typeDefinition,
|
|
343
|
+
};
|
|
343
344
|
})
|
|
344
|
-
.filter(Boolean)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
.split('/')
|
|
354
|
-
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
355
|
-
.join('')
|
|
356
|
-
.replace(/[^a-zA-Z0-9]/g, '')}Data`;
|
|
357
|
-
return typeName;
|
|
358
|
-
})
|
|
359
|
-
.filter(Boolean)
|
|
360
|
-
.join(' | ');
|
|
345
|
+
.filter(Boolean);
|
|
346
|
+
// Generate type definitions string
|
|
347
|
+
const typeDefinitions = pageTypeDefinitions.map((def) => `export ${def === null || def === void 0 ? void 0 : def.typeDefinition}`).join('\n\n');
|
|
348
|
+
// Generate string literals for each type
|
|
349
|
+
const typeStrings = pageTypeDefinitions
|
|
350
|
+
.map((def) => `export const ${def === null || def === void 0 ? void 0 : def.typeName}String = \`${def === null || def === void 0 ? void 0 : def.typeDefinition}\`;`)
|
|
351
|
+
.join('\n\n');
|
|
352
|
+
// Generate union type
|
|
353
|
+
const pageUnionTypes = pageTypeDefinitions.map((def) => def === null || def === void 0 ? void 0 : def.typeName).join(' | ');
|
|
361
354
|
return `
|
|
362
|
-
//
|
|
363
|
-
${
|
|
355
|
+
// Page data type definitions
|
|
356
|
+
${typeDefinitions}
|
|
357
|
+
|
|
358
|
+
// String versions of type definitions
|
|
359
|
+
${typeStrings}
|
|
364
360
|
|
|
365
|
-
//
|
|
361
|
+
// Union type of all page data types
|
|
366
362
|
export type PageDataUnion = ${pageUnionTypes || 'never'};`;
|
|
367
363
|
}
|
|
368
364
|
exports.default = generateWrapperCode;
|
package/lib/cjs/utils/helper.js
CHANGED
|
@@ -32,6 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
|
+
};
|
|
35
38
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
39
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
40
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -45,7 +48,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
48
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
49
|
};
|
|
47
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.getBlockCode = exports.isPagesKitBlockStudio = exports.getPreviewImageRelativePath = exports.downloadAsset = exports.isMetadataFile = exports.isDev = exports.isPathSafe = exports.
|
|
51
|
+
exports.safeParse = exports.getBlockCode = exports.isPagesKitBlockStudio = exports.getPreviewImageRelativePath = exports.downloadAsset = exports.isMetadataFile = exports.isDev = exports.isPathSafe = exports.logger = void 0;
|
|
49
52
|
exports.setBlockEntryFilesPattern = setBlockEntryFilesPattern;
|
|
50
53
|
exports.getBlockEntryFilesPattern = getBlockEntryFilesPattern;
|
|
51
54
|
exports.findComponentFiles = findComponentFiles;
|
|
@@ -64,14 +67,10 @@ const promises_2 = require("stream/promises");
|
|
|
64
67
|
const ufo_1 = require("ufo");
|
|
65
68
|
const yaml = __importStar(require("yaml"));
|
|
66
69
|
const constants_1 = require("../constants");
|
|
70
|
+
__exportStar(require("../constants"), exports);
|
|
67
71
|
exports.logger = console;
|
|
68
|
-
exports.libDir = 'lib';
|
|
69
|
-
exports.METADATA_FILE_NAME = '@metadata.json';
|
|
70
|
-
exports.PREVIEW_IMAGE_DIR = '@preview-images';
|
|
71
|
-
exports.NANOID_LENGTH = 16;
|
|
72
|
-
const DEFAULT_BLOCK_ENTRY_FILES_PATTERN = 'src/**/index.{ts,tsx,html}';
|
|
73
72
|
if (!process.env.BLOCK_ENTRY_FILES_PATTERN) {
|
|
74
|
-
process.env.BLOCK_ENTRY_FILES_PATTERN = DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
|
|
73
|
+
process.env.BLOCK_ENTRY_FILES_PATTERN = constants_1.DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
|
|
75
74
|
}
|
|
76
75
|
function normalizePattern(pattern) {
|
|
77
76
|
return pattern.replace(/^[/\\]+/, ''); // Remove leading slashes
|
|
@@ -80,7 +79,7 @@ function setBlockEntryFilesPattern(pattern) {
|
|
|
80
79
|
process.env.BLOCK_ENTRY_FILES_PATTERN = normalizePattern(pattern);
|
|
81
80
|
}
|
|
82
81
|
function getBlockEntryFilesPattern() {
|
|
83
|
-
return process.env.BLOCK_ENTRY_FILES_PATTERN || DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
|
|
82
|
+
return process.env.BLOCK_ENTRY_FILES_PATTERN || constants_1.DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
|
|
84
83
|
}
|
|
85
84
|
function findComponentFiles(options = {}) {
|
|
86
85
|
const { cwd = process.cwd(), filter } = options;
|
|
@@ -124,7 +123,7 @@ const isPathSafe = (filePath) => {
|
|
|
124
123
|
exports.isPathSafe = isPathSafe;
|
|
125
124
|
exports.isDev = process.env.BLOCKLET_MODE === 'development';
|
|
126
125
|
const isMetadataFile = (filePath) => {
|
|
127
|
-
return filePath.endsWith(
|
|
126
|
+
return filePath.endsWith(constants_1.METADATA_FILE_NAME);
|
|
128
127
|
};
|
|
129
128
|
exports.isMetadataFile = isMetadataFile;
|
|
130
129
|
const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* ({ asset, savePath, componentDid, }) {
|
|
@@ -155,7 +154,7 @@ const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* ({ asset
|
|
|
155
154
|
});
|
|
156
155
|
exports.downloadAsset = downloadAsset;
|
|
157
156
|
const getPreviewImageRelativePath = (name) => {
|
|
158
|
-
return path_1.default.join(
|
|
157
|
+
return path_1.default.join(constants_1.PREVIEW_IMAGE_DIR, name);
|
|
159
158
|
};
|
|
160
159
|
exports.getPreviewImageRelativePath = getPreviewImageRelativePath;
|
|
161
160
|
function initializeMetadata(tempFilePath) {
|
|
@@ -164,7 +163,7 @@ function initializeMetadata(tempFilePath) {
|
|
|
164
163
|
throw new Error('File path is required');
|
|
165
164
|
}
|
|
166
165
|
// file path is metadata file
|
|
167
|
-
const filePath = (0, exports.isMetadataFile)(tempFilePath) ? tempFilePath : path_1.default.join((0, path_1.dirname)(tempFilePath),
|
|
166
|
+
const filePath = (0, exports.isMetadataFile)(tempFilePath) ? tempFilePath : path_1.default.join((0, path_1.dirname)(tempFilePath), constants_1.METADATA_FILE_NAME);
|
|
168
167
|
if (!filePath) {
|
|
169
168
|
throw new Error('File path is required');
|
|
170
169
|
}
|
|
@@ -182,7 +181,7 @@ function initializeMetadata(tempFilePath) {
|
|
|
182
181
|
}
|
|
183
182
|
// Add id if not exists
|
|
184
183
|
if (!metadata.id) {
|
|
185
|
-
metadata.id = (0, nanoid_1.nanoid)(
|
|
184
|
+
metadata.id = (0, nanoid_1.nanoid)(constants_1.NANOID_LENGTH);
|
|
186
185
|
}
|
|
187
186
|
// Add createdAt if not exists
|
|
188
187
|
if (!metadata.createdAt) {
|
|
@@ -227,3 +226,12 @@ const getBlockCode = (filePath) => {
|
|
|
227
226
|
return fs_1.default.readFileSync(codeFile, 'utf8');
|
|
228
227
|
};
|
|
229
228
|
exports.getBlockCode = getBlockCode;
|
|
229
|
+
const safeParse = (text) => {
|
|
230
|
+
try {
|
|
231
|
+
return JSON.parse(text);
|
|
232
|
+
}
|
|
233
|
+
catch (_a) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
exports.safeParse = safeParse;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import path from 'path';
|
|
1
2
|
export const PAGES_KIT_DID = 'z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o';
|
|
2
3
|
export const PAGES_KIT_RESOURCE_TYPE = 'page';
|
|
3
4
|
export const PAGES_KIT_BLOCK_STUDIO_DID = 'z2qa7rr3eUyVnWp2PCxEVARuUfLFh6cE5V2xV';
|
|
4
5
|
export const PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = 'page';
|
|
5
6
|
export const MEDIA_KIT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9';
|
|
6
7
|
export const MEDIA_KIT_RESOURCE_TYPE = 'imgpack';
|
|
8
|
+
export const NEW_BLOCK_TEMPLATE_PATH = path.join(__dirname, 'new-block-template', 'index.tsx');
|
|
9
|
+
export const NEW_BLOCK_TEMPLATE_METADATA_PATH = path.join(__dirname, 'new-block-template', '@metadata.json');
|
|
10
|
+
export const libDir = 'lib';
|
|
11
|
+
export const METADATA_FILE_NAME = '@metadata.json';
|
|
12
|
+
export const PREVIEW_IMAGE_DIR = '@preview-images';
|
|
13
|
+
export const NANOID_LENGTH = 16;
|
|
14
|
+
export const 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,50 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
// default export
|
|
14
|
+
export default function HelloWorld({ title = 'Hello World', logo, description, copyright }) {
|
|
15
|
+
return (_jsxs("div", { style: {
|
|
16
|
+
display: 'flex',
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
padding: '16px 0',
|
|
20
|
+
}, children: [title && _jsx("h1", { children: title }), logo && (_jsx("img", { src: typeof logo === 'object' ? logo.url : logo, alt: "logo", style: {
|
|
21
|
+
margin: '16px 0',
|
|
22
|
+
maxWidth: '200px',
|
|
23
|
+
} })), description && (_jsx("div", { style: {
|
|
24
|
+
color: '#666',
|
|
25
|
+
marginTop: '8px',
|
|
26
|
+
}, children: description })), copyright && (_jsx("div", { style: {
|
|
27
|
+
color: '#999',
|
|
28
|
+
fontSize: '12px',
|
|
29
|
+
marginTop: '16px',
|
|
30
|
+
}, children: copyright }))] }));
|
|
31
|
+
}
|
|
32
|
+
// export edit component
|
|
33
|
+
export const EditComponent = (_a) => {
|
|
34
|
+
var { onChange } = _a, props = __rest(_a, ["onChange"]);
|
|
35
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: [_jsx("div", { style: {
|
|
36
|
+
fontSize: '14px',
|
|
37
|
+
fontWeight: 500,
|
|
38
|
+
color: '#333',
|
|
39
|
+
padding: '8px 0',
|
|
40
|
+
borderBottom: '1px solid #eee',
|
|
41
|
+
}, children: "Footer Parameters" }), _jsx("input", { id: "copyright-input", type: "text", style: {
|
|
42
|
+
width: '100%',
|
|
43
|
+
padding: '8px 12px',
|
|
44
|
+
border: '1px solid #ddd',
|
|
45
|
+
borderRadius: '4px',
|
|
46
|
+
fontSize: '14px',
|
|
47
|
+
transition: 'border-color 0.3s',
|
|
48
|
+
outline: 'none',
|
|
49
|
+
}, value: props.copyright || '', onChange: (e) => onChange === null || onChange === void 0 ? void 0 : onChange({ copyright: e.target.value }), placeholder: "Please Input Copyright" })] }));
|
|
50
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -11,7 +11,8 @@ import { Router } from 'express';
|
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import { isEqual, keyBy, set } from 'lodash';
|
|
13
13
|
import path from 'path';
|
|
14
|
-
import {
|
|
14
|
+
import { METADATA_FILE_NAME, NEW_BLOCK_TEMPLATE_PATH, NEW_BLOCK_TEMPLATE_METADATA_PATH } from '../constants';
|
|
15
|
+
import { isPathSafe, isDev, downloadAsset, isMetadataFile, getPreviewImageRelativePath, initializeMetadata, findComponentFiles, getBlockStudioInfo, getBlockCode, getBlockEntryFilesPattern, safeParse, } from '../utils/helper';
|
|
15
16
|
export const initBlockStudioRouter = Router();
|
|
16
17
|
const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.svg'];
|
|
17
18
|
initBlockStudioRouter.get('/', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -37,11 +38,6 @@ initBlockStudioRouter.get('/', (req, res) => __awaiter(void 0, void 0, void 0, f
|
|
|
37
38
|
return fs.createReadStream(filePath).pipe(res);
|
|
38
39
|
}
|
|
39
40
|
const metadata = initializeMetadata(filePath);
|
|
40
|
-
const code = getBlockCode(filePath);
|
|
41
|
-
if (code) {
|
|
42
|
-
set(metadata, 'renderer.script', code);
|
|
43
|
-
set(metadata, 'renderer.type', 'react-component');
|
|
44
|
-
}
|
|
45
41
|
return res.json(metadata);
|
|
46
42
|
}
|
|
47
43
|
catch (error) {
|
|
@@ -81,16 +77,54 @@ initBlockStudioRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0,
|
|
|
81
77
|
});
|
|
82
78
|
}
|
|
83
79
|
}
|
|
84
|
-
res.json({ success: true, content: mergedContent, message: 'Updated' });
|
|
85
|
-
// save metadata without renderer after response
|
|
86
|
-
delete mergedContent.renderer;
|
|
87
80
|
fs.writeFileSync(filePath, JSON.stringify(mergedContent, null, 2));
|
|
88
|
-
return
|
|
81
|
+
return res.json({ success: true, content: mergedContent, message: 'Updated' });
|
|
89
82
|
}
|
|
90
83
|
catch (error) {
|
|
91
84
|
return res.status(500).json({ error: 'Failed to write file' });
|
|
92
85
|
}
|
|
93
86
|
}));
|
|
87
|
+
initBlockStudioRouter.post('/create', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
if (!isDev) {
|
|
89
|
+
return res.status(403).json({ error: 'Only available in development mode' });
|
|
90
|
+
}
|
|
91
|
+
const { name, description } = req.body;
|
|
92
|
+
if (!name) {
|
|
93
|
+
return res.status(400).json({ error: 'Name is required' });
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const pattern = getBlockEntryFilesPattern();
|
|
97
|
+
const baseDir = path.dirname(pattern.replace(/\*\*?/g, ''));
|
|
98
|
+
const blockDir = path.join(baseDir, name);
|
|
99
|
+
const metadataPath = path.join(blockDir, METADATA_FILE_NAME);
|
|
100
|
+
const indexPath = path.join(blockDir, 'index.tsx');
|
|
101
|
+
// Check if block already exists
|
|
102
|
+
if (fs.existsSync(blockDir)) {
|
|
103
|
+
return res.status(409).json({ error: 'Block already exists' });
|
|
104
|
+
}
|
|
105
|
+
// Create block directory
|
|
106
|
+
fs.mkdirSync(blockDir, { recursive: true });
|
|
107
|
+
// Initialize metadata
|
|
108
|
+
let metadata = initializeMetadata(metadataPath);
|
|
109
|
+
metadata.name = name;
|
|
110
|
+
metadata.description = description || '';
|
|
111
|
+
metadata.createdAt = new Date().toISOString();
|
|
112
|
+
metadata.updatedAt = new Date().toISOString();
|
|
113
|
+
// get template metadata from @metadata.json
|
|
114
|
+
const metadataContent = fs.readFileSync(NEW_BLOCK_TEMPLATE_METADATA_PATH, 'utf-8');
|
|
115
|
+
metadata = Object.assign(Object.assign({}, metadata), safeParse(metadataContent));
|
|
116
|
+
// Write metadata file
|
|
117
|
+
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
|
|
118
|
+
// Copy template file to index.tsx
|
|
119
|
+
const templateContent = fs.readFileSync(NEW_BLOCK_TEMPLATE_PATH, 'utf-8');
|
|
120
|
+
fs.writeFileSync(indexPath, templateContent);
|
|
121
|
+
return res.json({ success: true, metadata });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('Failed to create block:', error);
|
|
125
|
+
return res.status(500).json({ error: 'Failed to create block' });
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
94
128
|
initBlockStudioRouter.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
129
|
const { withBlockletData = true } = req.query;
|
|
96
130
|
const allBlocks = yield findComponentFiles();
|
|
@@ -98,7 +98,7 @@ initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0, fun
|
|
|
98
98
|
const buildProcess = spawn('pnpm', ['run', 'build-lib'], {
|
|
99
99
|
stdio: 'inherit',
|
|
100
100
|
shell: true,
|
|
101
|
-
env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(',') }),
|
|
101
|
+
env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(','), NODE_OPTIONS: '--max_old_space_size=16384' }),
|
|
102
102
|
});
|
|
103
103
|
yield new Promise((resolve, reject) => {
|
|
104
104
|
buildProcess.on('close', (code) => {
|
|
@@ -107,6 +107,10 @@ initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0, fun
|
|
|
107
107
|
else
|
|
108
108
|
reject(new Error(`Build process exited with code ${code}`));
|
|
109
109
|
});
|
|
110
|
+
buildProcess.on('error', (error) => {
|
|
111
|
+
console.error('Build process error:', error);
|
|
112
|
+
reject(error);
|
|
113
|
+
});
|
|
110
114
|
});
|
|
111
115
|
const dir = getExportDir(projectId, releaseId);
|
|
112
116
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
// import typescript from '@rollup/plugin-typescript';
|
|
12
12
|
import { readFileSync, existsSync } from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
|
+
import { joinURL } from 'ufo';
|
|
14
15
|
import pages, { DefaultPageStrategy } from 'vite-plugin-react-pages';
|
|
15
16
|
import { findComponentFiles, setBlockEntryFilesPattern, getBlockEntryFilesPattern, getBlockName, logger, } from '../utils/helper';
|
|
16
17
|
import { initHtmlPreviewTransformPlugin, VIRTUAL_MODULE_ID, readHtmlFiles, generateComponent, } from './vite-plugin-html-transform';
|
|
@@ -72,18 +73,13 @@ export function initBlockStudioPlugins(options) {
|
|
|
72
73
|
formats: ['es', !multiMode ? 'umd' : 'cjs'],
|
|
73
74
|
fileName: (format, entryName) => `${format}/${entryName}.js`,
|
|
74
75
|
}, rollupOptions: {
|
|
75
|
-
external:
|
|
76
|
-
'react',
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// '@emotion/react',
|
|
83
|
-
// '@emotion/styled',
|
|
84
|
-
'@arcblock/ux',
|
|
85
|
-
'@arcblock/did-connect',
|
|
86
|
-
],
|
|
76
|
+
external: (id) => {
|
|
77
|
+
const skip = ['react', 'crypto'];
|
|
78
|
+
if (skip.some((s) => id === s)) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
},
|
|
87
83
|
output: {
|
|
88
84
|
chunkFileNames: () => {
|
|
89
85
|
return '[format]/_chunks/[name]-[hash].js';
|
|
@@ -91,22 +87,13 @@ export function initBlockStudioPlugins(options) {
|
|
|
91
87
|
// 为所有外部依赖提供全局变量
|
|
92
88
|
globals: {
|
|
93
89
|
react: 'React',
|
|
94
|
-
'react-dom': 'ReactDOM',
|
|
95
|
-
'react-is': 'ReactIs',
|
|
96
|
-
'react-router-dom': 'ReactRouterDOM',
|
|
97
|
-
'react/jsx-runtime': 'ReactJsxRuntime',
|
|
98
|
-
// '@emotion/react': 'emotionReact',
|
|
99
|
-
// '@emotion/styled': 'emotionStyled',
|
|
100
|
-
'@mui/material': 'MUI',
|
|
101
|
-
'@arcblock/ux': 'ArcBlockUX',
|
|
102
|
-
'@arcblock/did-connect': 'ArcBlockDidConnect',
|
|
103
90
|
},
|
|
104
91
|
paths: {
|
|
105
|
-
|
|
106
|
-
|
|
92
|
+
// Redirect 'react' imports to '@blocklet/pages-kit/builtin/react'
|
|
93
|
+
react: '@blocklet/pages-kit/builtin/react',
|
|
107
94
|
},
|
|
108
95
|
// 确保正确处理命名导出和默认导出
|
|
109
|
-
|
|
96
|
+
interop: 'auto',
|
|
110
97
|
},
|
|
111
98
|
} }, _config === null || _config === void 0 ? void 0 : _config.build),
|
|
112
99
|
};
|
|
@@ -126,21 +113,23 @@ export function initBlockStudioPlugins(options) {
|
|
|
126
113
|
const pageId = `/${blockName}`;
|
|
127
114
|
const dirPath = path.dirname(filePath);
|
|
128
115
|
const metadataPath = path.join(dirPath, '@metadata.json');
|
|
116
|
+
const dataPath = isHtml ? `${VIRTUAL_MODULE_ID}?dir=${dirPath}` : filePath;
|
|
129
117
|
api.addPageData({
|
|
130
118
|
pageId,
|
|
131
|
-
dataPath
|
|
119
|
+
dataPath,
|
|
132
120
|
staticData: isHtml
|
|
133
121
|
? {
|
|
134
|
-
|
|
135
|
-
dataPath
|
|
136
|
-
code: generateComponent(readHtmlFiles(dirPath
|
|
122
|
+
isHtml: true,
|
|
123
|
+
dataPath,
|
|
124
|
+
code: generateComponent(readHtmlFiles(dirPath)),
|
|
137
125
|
blockName,
|
|
138
126
|
dirPath,
|
|
127
|
+
importPath: joinURL('@id', dataPath),
|
|
139
128
|
metadataPath,
|
|
140
129
|
}
|
|
141
|
-
: Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: readFileSync(file.path, 'utf-8'), dataPath
|
|
142
|
-
|
|
143
|
-
metadataPath }),
|
|
130
|
+
: Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: readFileSync(file.path, 'utf-8'), dataPath,
|
|
131
|
+
blockName,
|
|
132
|
+
dirPath, importPath: joinURL('@fs', dataPath), metadataPath }),
|
|
144
133
|
});
|
|
145
134
|
});
|
|
146
135
|
});
|
|
@@ -161,6 +150,15 @@ export function initBlockStudioPlugins(options) {
|
|
|
161
150
|
// maxConcurrent: 5, // 可选,默认值
|
|
162
151
|
// timeout: 30 * 1000, // 可选,默认值 30 秒
|
|
163
152
|
// }),
|
|
153
|
+
{
|
|
154
|
+
name: 'build-force-exit',
|
|
155
|
+
apply: 'build',
|
|
156
|
+
enforce: 'post',
|
|
157
|
+
closeBundle() {
|
|
158
|
+
// ensure vite build exit
|
|
159
|
+
process.exit(0);
|
|
160
|
+
},
|
|
161
|
+
},
|
|
164
162
|
];
|
|
165
163
|
}
|
|
166
164
|
export default initBlockStudioPlugins;
|