* 解析项目文件(ZIP格式),提取所有数据 * @returns 解析后的数据对象
()
| 236 | * @returns 解析后的数据对象 |
| 237 | */ |
| 238 | private async parseProjectFile(): Promise<{ |
| 239 | serializedStageObjects: any[]; |
| 240 | tags: string[]; |
| 241 | references: { sections: Record<string, string[]>; files: string[] }; |
| 242 | metadata: PrgMetadata; |
| 243 | readme?: string; |
| 244 | }> { |
| 245 | const fileContent = await this.fs.read(this.uri); |
| 246 | const reader = new ZipReader(new Uint8ArrayReader(fileContent)); |
| 247 | const entries = await reader.getEntries(); |
| 248 | |
| 249 | let serializedStageObjects: any[] = []; |
| 250 | let tags: string[] = []; |
| 251 | let references: { sections: Record<string, string[]>; files: string[] } = { sections: {}, files: [] }; |
| 252 | let metadata: PrgMetadata = createDefaultMetadata("2.0.0"); |
| 253 | let readme: string | undefined = undefined; |
| 254 | |
| 255 | for (const entry of entries) { |
| 256 | if (!entry.directory) { |
| 257 | if (entry.filename === "stage.msgpack") { |
| 258 | const stageRawData = await entry.getData!(new Uint8ArrayWriter()); |
| 259 | serializedStageObjects = this.decoder.decode(stageRawData) as any[]; |
| 260 | } else if (entry.filename === "tags.msgpack") { |
| 261 | const tagsRawData = await entry.getData!(new Uint8ArrayWriter()); |
| 262 | tags = this.decoder.decode(tagsRawData) as string[]; |
| 263 | } else if (entry.filename === "reference.msgpack") { |
| 264 | const referenceRawData = await entry.getData!(new Uint8ArrayWriter()); |
| 265 | references = this.decoder.decode(referenceRawData) as { sections: Record<string, string[]>; files: string[] }; |
| 266 | } else if (entry.filename === "metadata.msgpack") { |
| 267 | const metadataRawData = await entry.getData!(new Uint8ArrayWriter()); |
| 268 | const decodedMetadata = this.decoder.decode(metadataRawData) as any; |
| 269 | // 验证并规范化 metadata |
| 270 | if (isValidMetadata(decodedMetadata)) { |
| 271 | metadata = decodedMetadata; |
| 272 | } else { |
| 273 | // 如果格式不正确,使用默认值 |
| 274 | metadata = createDefaultMetadata("2.0.0"); |
| 275 | } |
| 276 | } else if (entry.filename === "README.md") { |
| 277 | const readmeRawData = await entry.getData!(new Uint8ArrayWriter()); |
| 278 | readme = new TextDecoder().decode(readmeRawData); |
| 279 | } else if (entry.filename.startsWith("attachments/")) { |
| 280 | const match = entry.filename.trim().match(/^attachments\/([a-zA-Z0-9-]+)\.([a-zA-Z0-9]+)$/); |
| 281 | if (!match) { |
| 282 | console.warn("[Project] 附件文件名不符合规范: %s", entry.filename); |
| 283 | continue; |
| 284 | } |
| 285 | const uuid = match[1]; |
| 286 | const ext = match[2]; |
| 287 | const type = mime.getType(ext) || "application/octet-stream"; |
| 288 | const attachment = await entry.getData!(new BlobWriter(type)); |
| 289 | this.attachments.set(uuid, attachment); |
| 290 | } |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | return { serializedStageObjects, tags, references, metadata, readme }; |
| 295 | } |
no test coverage detected