cocos2d-cli 1.6.1 → 1.6.3
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 +429 -80
- package/bin/cocos2d-cli.js +11 -31
- package/package.json +3 -3
- package/src/commands/screenshot.js +17 -9
- package/src/lib/cc/CCLabel.js +27 -2
- package/src/lib/cc/CCRichText.js +44 -0
- package/src/lib/cc/CCSprite.js +2 -2
- package/src/lib/cc/index.js +3 -1
- package/src/lib/json-parser.js +27 -8
- package/src/lib/screenshot/index.html +1 -1
- package/src/lib/screenshot-core.js +78 -53
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Screenshot Core Module
|
|
2
|
+
* Screenshot Core Module
|
|
3
3
|
* 渲染 JSON 数据并使用 Playwright 截图
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -16,6 +16,7 @@ const DEFAULT_CONFIG = {
|
|
|
16
16
|
outputDir: process.cwd(),
|
|
17
17
|
viewport: { width: 750, height: 1334 },
|
|
18
18
|
fullPage: true,
|
|
19
|
+
debugBounds: false,
|
|
19
20
|
timeout: 30000,
|
|
20
21
|
waitTime: 1000
|
|
21
22
|
};
|
|
@@ -35,7 +36,7 @@ async function createTempWorkDir() {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// 复制内置资源到临时目录
|
|
38
|
-
async function copyBuiltInAssets(tempDir) {
|
|
39
|
+
async function copyBuiltInAssets(tempDir, logs) {
|
|
39
40
|
const assetsDir = getAssetsDir();
|
|
40
41
|
const assets = ['index.html', 'favicon.ico'];
|
|
41
42
|
|
|
@@ -45,13 +46,17 @@ async function copyBuiltInAssets(tempDir) {
|
|
|
45
46
|
try {
|
|
46
47
|
await fs.copyFile(src, dest);
|
|
47
48
|
} catch (err) {
|
|
48
|
-
|
|
49
|
+
logs.push({
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
type: 'warning',
|
|
52
|
+
text: `Could not copy ${asset}: ${err.message}`
|
|
53
|
+
});
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
// 静态文件服务器
|
|
54
|
-
async function startServer(staticDir) {
|
|
59
|
+
async function startServer(staticDir, logs) {
|
|
55
60
|
return new Promise((resolve, reject) => {
|
|
56
61
|
const server = http.createServer(async (req, res) => {
|
|
57
62
|
try {
|
|
@@ -93,7 +98,11 @@ async function startServer(staticDir) {
|
|
|
93
98
|
res.writeHead(404);
|
|
94
99
|
res.end();
|
|
95
100
|
} else {
|
|
96
|
-
|
|
101
|
+
logs.push({
|
|
102
|
+
timestamp: new Date().toISOString(),
|
|
103
|
+
type: 'server-error',
|
|
104
|
+
text: `${req.url}: ${err.message}`
|
|
105
|
+
});
|
|
97
106
|
res.writeHead(500);
|
|
98
107
|
res.end();
|
|
99
108
|
}
|
|
@@ -105,11 +114,17 @@ async function startServer(staticDir) {
|
|
|
105
114
|
}
|
|
106
115
|
|
|
107
116
|
// 递归删除目录
|
|
108
|
-
async function removeDir(dirPath) {
|
|
117
|
+
async function removeDir(dirPath, logs) {
|
|
109
118
|
try {
|
|
110
119
|
await fs.rm(dirPath, { recursive: true, force: true });
|
|
111
120
|
} catch (err) {
|
|
112
|
-
|
|
121
|
+
if (logs) {
|
|
122
|
+
logs.push({
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
type: 'warning',
|
|
125
|
+
text: `Could not remove temp dir: ${err.message}`
|
|
126
|
+
});
|
|
127
|
+
}
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
130
|
|
|
@@ -136,6 +151,16 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
136
151
|
let tempDir = null;
|
|
137
152
|
const logs = [];
|
|
138
153
|
let screenshotPath = null;
|
|
154
|
+
let logDir = null;
|
|
155
|
+
|
|
156
|
+
const addLog = (type, text, extra = {}) => {
|
|
157
|
+
logs.push({
|
|
158
|
+
timestamp: new Date().toISOString(),
|
|
159
|
+
type,
|
|
160
|
+
text,
|
|
161
|
+
...extra
|
|
162
|
+
});
|
|
163
|
+
};
|
|
139
164
|
|
|
140
165
|
try {
|
|
141
166
|
const timestamp = Date.now();
|
|
@@ -152,32 +177,32 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
152
177
|
|
|
153
178
|
// 创建临时工作目录
|
|
154
179
|
tempDir = await createTempWorkDir();
|
|
155
|
-
|
|
180
|
+
addLog('info', `Temp dir: ${tempDir}`);
|
|
156
181
|
|
|
157
182
|
// 复制内置资源到临时目录
|
|
158
|
-
await copyBuiltInAssets(tempDir);
|
|
159
|
-
|
|
183
|
+
await copyBuiltInAssets(tempDir, logs);
|
|
184
|
+
|
|
160
185
|
// 复制用户的 JSON 文件到临时目录
|
|
161
186
|
const destJsonPath = path.join(tempDir, 'data.json');
|
|
162
187
|
await fs.copyFile(config.jsonPath, destJsonPath);
|
|
163
|
-
|
|
188
|
+
addLog('info', `JSON: ${config.jsonPath}`);
|
|
164
189
|
|
|
165
190
|
// 截图输出路径
|
|
166
191
|
screenshotPath = path.join(config.outputDir, `screenshot-${timestamp}.png`);
|
|
167
192
|
|
|
168
193
|
// 启动HTTP服务器
|
|
169
|
-
|
|
170
|
-
server = await startServer(tempDir);
|
|
194
|
+
addLog('info', 'Starting Server');
|
|
195
|
+
server = await startServer(tempDir, logs);
|
|
171
196
|
const serverUrl = `http://127.0.0.1:${server.address().port}`;
|
|
172
|
-
|
|
197
|
+
addLog('info', `Server: ${serverUrl}`);
|
|
173
198
|
|
|
174
199
|
// 启动浏览器
|
|
175
|
-
|
|
200
|
+
addLog('info', 'Launching Browser');
|
|
176
201
|
browser = await chromium.launch({
|
|
177
202
|
headless: true,
|
|
178
203
|
channel: 'chrome'
|
|
179
204
|
});
|
|
180
|
-
|
|
205
|
+
addLog('info', 'Browser launched');
|
|
181
206
|
|
|
182
207
|
const page = await browser.newPage({
|
|
183
208
|
viewport: config.viewport
|
|
@@ -186,75 +211,75 @@ async function takeScreenshot(userConfig = {}) {
|
|
|
186
211
|
// 监听浏览器控制台日志
|
|
187
212
|
page.on('console', msg => {
|
|
188
213
|
const text = msg.text();
|
|
189
|
-
|
|
190
|
-
timestamp: new Date().toISOString(),
|
|
191
|
-
type: msg.type(),
|
|
192
|
-
text
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
if (msg.type() === 'error') {
|
|
196
|
-
console.error(`[Browser Error] ${text}`);
|
|
197
|
-
} else if (msg.type() === 'warning') {
|
|
198
|
-
console.warn(`[Browser Warning] ${text}`);
|
|
199
|
-
} else {
|
|
200
|
-
console.log(`[Browser] ${text}`);
|
|
201
|
-
}
|
|
214
|
+
addLog(msg.type(), text);
|
|
202
215
|
});
|
|
203
216
|
|
|
204
217
|
page.on('pageerror', error => {
|
|
205
|
-
|
|
206
|
-
timestamp: new Date().toISOString(),
|
|
207
|
-
type: 'pageerror',
|
|
208
|
-
text: error.message
|
|
209
|
-
});
|
|
210
|
-
console.error('[Page Error]', error.message);
|
|
218
|
+
addLog('pageerror', error.message);
|
|
211
219
|
});
|
|
212
220
|
|
|
213
221
|
page.on('requestfailed', request => {
|
|
214
222
|
const failure = request.failure();
|
|
215
223
|
const errorText = failure ? failure.errorText : 'Unknown error';
|
|
216
|
-
|
|
217
|
-
timestamp: new Date().toISOString(),
|
|
218
|
-
type: 'requestfailed',
|
|
219
|
-
url: request.url(),
|
|
220
|
-
error: errorText
|
|
221
|
-
});
|
|
222
|
-
console.error(`[Request Failed] ${request.url()}`);
|
|
224
|
+
addLog('requestfailed', request.url(), { error: errorText });
|
|
223
225
|
});
|
|
224
226
|
|
|
225
227
|
// 加载页面
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
addLog('info', 'Loading Page');
|
|
229
|
+
const pageUrl = config.debugBounds
|
|
230
|
+
? `${serverUrl}/index.html?debugBounds=true`
|
|
231
|
+
: `${serverUrl}/index.html`;
|
|
232
|
+
await page.goto(pageUrl, {
|
|
228
233
|
waitUntil: 'networkidle',
|
|
229
234
|
timeout: config.timeout
|
|
230
235
|
});
|
|
231
|
-
|
|
236
|
+
addLog('info', 'Page loaded');
|
|
232
237
|
|
|
233
238
|
// 等待渲染
|
|
234
|
-
|
|
239
|
+
addLog('info', 'Waiting for Render');
|
|
235
240
|
await page.waitForTimeout(config.waitTime);
|
|
236
|
-
|
|
241
|
+
addLog('info', 'Wait complete');
|
|
237
242
|
|
|
238
243
|
// 截图
|
|
239
|
-
|
|
244
|
+
addLog('info', 'Taking Screenshot');
|
|
240
245
|
await page.screenshot({
|
|
241
246
|
path: screenshotPath,
|
|
242
247
|
fullPage: config.fullPage
|
|
243
248
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
console.log('\n=== Done ===');
|
|
249
|
+
addLog('info', `Screenshot saved: ${screenshotPath}`);
|
|
250
|
+
addLog('info', 'Done');
|
|
247
251
|
|
|
248
252
|
return { screenshotPath, logs };
|
|
249
253
|
|
|
250
254
|
} catch (error) {
|
|
251
|
-
|
|
255
|
+
addLog('error', error.message);
|
|
256
|
+
try {
|
|
257
|
+
logDir = path.join(config.outputDir, `screenshot-logs-${Date.now()}`);
|
|
258
|
+
await fs.mkdir(logDir, { recursive: true });
|
|
259
|
+
await fs.writeFile(
|
|
260
|
+
path.join(logDir, 'logs.json'),
|
|
261
|
+
JSON.stringify({
|
|
262
|
+
error: error.message,
|
|
263
|
+
jsonPath: config.jsonPath,
|
|
264
|
+
outputDir: config.outputDir,
|
|
265
|
+
viewport: config.viewport,
|
|
266
|
+
fullPage: config.fullPage,
|
|
267
|
+
debugBounds: config.debugBounds,
|
|
268
|
+
timeout: config.timeout,
|
|
269
|
+
waitTime: config.waitTime,
|
|
270
|
+
screenshotPath,
|
|
271
|
+
logs
|
|
272
|
+
}, null, 2),
|
|
273
|
+
'utf8'
|
|
274
|
+
);
|
|
275
|
+
} catch (_) {}
|
|
276
|
+
error.logDir = logDir;
|
|
252
277
|
throw error;
|
|
253
278
|
} finally {
|
|
254
279
|
// 清理资源
|
|
255
280
|
if (browser) await browser.close().catch(() => {});
|
|
256
281
|
if (server) server.close();
|
|
257
|
-
if (tempDir) await removeDir(tempDir);
|
|
282
|
+
if (tempDir) await removeDir(tempDir, logs);
|
|
258
283
|
}
|
|
259
284
|
}
|
|
260
285
|
|