@blocklet/pages-kit-block-studio 0.1.4 → 0.1.7
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.tsx +89 -0
- package/lib/cjs/middlewares/init-block-studio-router.js +42 -0
- package/lib/cjs/plugins/vite-plugin-html-transform.js +46 -11
- 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.tsx +89 -0
- package/lib/esm/middlewares/init-block-studio-router.js +43 -1
- package/lib/esm/plugins/vite-plugin-html-transform.js +46 -11
- 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/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/helper.d.ts +2 -4
- package/package.json +9 -6
- 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,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'];
|
|
@@ -89,6 +90,47 @@ exports.initBlockStudioRouter.post('/', (req, res) => __awaiter(void 0, void 0,
|
|
|
89
90
|
return res.status(500).json({ error: 'Failed to write file' });
|
|
90
91
|
}
|
|
91
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
|
+
}));
|
|
92
134
|
exports.initBlockStudioRouter.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
135
|
const { withBlockletData = true } = req.query;
|
|
94
136
|
const allBlocks = yield (0, helper_1.findComponentFiles)();
|
|
@@ -170,10 +170,24 @@ ${content.trim()}`;
|
|
|
170
170
|
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
|
171
171
|
<meta http-equiv="Referrer-Policy" content="no-referrer">
|
|
172
172
|
<meta http-equiv="Permissions-Policy" content="accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()">`;
|
|
173
|
+
const autoHeightScript = `<script>
|
|
174
|
+
(function() {
|
|
175
|
+
if ('ResizeObserver' in window) {
|
|
176
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
177
|
+
const height = document.documentElement.scrollHeight;
|
|
178
|
+
window.parent.postMessage({ height }, '*');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
resizeObserver.observe(document.documentElement);
|
|
182
|
+
}
|
|
183
|
+
})();
|
|
184
|
+
</script>`;
|
|
173
185
|
// 将处理后的相对路径引入的 CSS 和 JS 注入到 HTML 中
|
|
174
186
|
const htmlContent = htmlWithoutRelativeImport
|
|
175
187
|
.replace('<head>', `<head>${securityHeaders}`)
|
|
176
188
|
.replace('</head>', `${cssContents.map((css) => `<style>${css.trim()}</style>`).join('\n')}
|
|
189
|
+
|
|
190
|
+
${autoHeightScript}
|
|
177
191
|
</head>`)
|
|
178
192
|
.replace('</body>', `
|
|
179
193
|
${jsContents.map((js) => `<script>${js}</script>`).join('\n')}
|
|
@@ -192,19 +206,40 @@ ${content.trim()}`;
|
|
|
192
206
|
}
|
|
193
207
|
function generateComponent(content, _isDev = true) {
|
|
194
208
|
const htmlContent = content.html;
|
|
195
|
-
const { name } = content;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return `import { createElement } from 'react';
|
|
209
|
+
// const { name } = content;
|
|
210
|
+
return `import React, { useEffect, useRef } from 'react';
|
|
211
|
+
|
|
212
|
+
const htmlContent = ${htmlContent};
|
|
200
213
|
|
|
201
214
|
export default function HtmlPreview() {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
215
|
+
const iframeRef = useRef(null);
|
|
216
|
+
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
const iframe = iframeRef.current;
|
|
219
|
+
if (!iframe) return;
|
|
220
|
+
|
|
221
|
+
const handleMessage = (event) => {
|
|
222
|
+
if (event.source === iframe.contentWindow) {
|
|
223
|
+
const height = event.data.height;
|
|
224
|
+
if (height) {
|
|
225
|
+
iframe.style.height = height + 'px';
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
window.addEventListener('message', handleMessage);
|
|
231
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
232
|
+
}, []);
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<iframe
|
|
236
|
+
ref={iframeRef}
|
|
237
|
+
style={{ border: 'none', width: '100%', height: '0px', maxHeight: '100vh' }}
|
|
238
|
+
sandbox="allow-scripts"
|
|
239
|
+
title="HtmlPreview"
|
|
240
|
+
srcDoc={htmlContent}
|
|
241
|
+
/>
|
|
242
|
+
);
|
|
208
243
|
}`;
|
|
209
244
|
}
|
|
210
245
|
function initHtmlPreviewTransformPlugin() {
|