sloth-d2c-mcp 1.0.4-beta81 → 1.0.4-beta83

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.
@@ -23,7 +23,7 @@ export class FileManager {
23
23
  Logger.log(`已设置工作目录根路径: ${rootPath}`);
24
24
  }
25
25
  getWorkspaceRoot() {
26
- return this.workspaceRoot;
26
+ return this.workspaceRoot || './';
27
27
  }
28
28
  /**
29
29
  * 生成文件路径
@@ -35,7 +35,7 @@ export class FileManager {
35
35
  getFilePath(fileKey, nodeId, filename) {
36
36
  // 清理文件名中的特殊字符
37
37
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_]/g, '_');
38
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_:]/g, '_') : 'root';
38
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_]/g, '_') : 'root';
39
39
  const cleanFilename = filename.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_.]/g, '_');
40
40
  return path.join(this.baseDir, cleanFileKey, cleanNodeId, cleanFilename);
41
41
  }
@@ -54,7 +54,7 @@ export class FileManager {
54
54
  }
55
55
  // 清理文件名中的特殊字符
56
56
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_]/g, '_');
57
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_:]/g, '_') : 'root';
57
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_]/g, '_') : 'root';
58
58
  const cleanFilename = filename.replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3400-\u4dbf-_.]/g, '_');
59
59
  if (skipParsePath) {
60
60
  return path.join(this.workspaceRoot, '.sloth', fileKey, nodeId || 'root', cleanFilename);
@@ -179,7 +179,7 @@ export class FileManager {
179
179
  async cleanupNode(fileKey, nodeId) {
180
180
  try {
181
181
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9-_]/g, '_');
182
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_:]/g, '_') : 'root';
182
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_]/g, '_') : 'root';
183
183
  const nodeDir = path.join(this.baseDir, cleanFileKey, cleanNodeId);
184
184
  await fs.rm(nodeDir, { recursive: true, force: true });
185
185
  Logger.log(`节点目录已清理: ${nodeDir}`);
@@ -234,7 +234,7 @@ export class FileManager {
234
234
  */
235
235
  getNodeDir(fileKey, nodeId) {
236
236
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9-_]/g, '_');
237
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_:]/g, '_') : 'root';
237
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_]/g, '_') : 'root';
238
238
  return path.join(this.baseDir, cleanFileKey, cleanNodeId);
239
239
  }
240
240
  /**
@@ -588,9 +588,6 @@ export class FileManager {
588
588
  */
589
589
  async saveComponentsDatabase(components) {
590
590
  const workspaceRoot = this.getWorkspaceRoot();
591
- if (!workspaceRoot) {
592
- throw new Error('工作目录根路径未设置,无法保存组件数据库');
593
- }
594
591
  const slothDir = path.join(workspaceRoot, '.sloth');
595
592
  const componentsPath = path.join(slothDir, 'components.json');
596
593
  // 确保目录存在
@@ -706,7 +703,7 @@ export class FileManager {
706
703
  now.getMinutes().toString().padStart(2, '0') +
707
704
  now.getSeconds().toString().padStart(2, '0');
708
705
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9-_]/g, '_');
709
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_:]/g, '_') : 'root';
706
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_]/g, '_') : 'root';
710
707
  // 归档路径:.sloth/{fileKey}/{nodeId}/history/{timestamp}/absolute.html
711
708
  const archiveDir = path.join(this.workspaceRoot, '.sloth', cleanFileKey, cleanNodeId, 'history', timestamp);
712
709
  try {
@@ -751,7 +748,7 @@ export class FileManager {
751
748
  return [];
752
749
  }
753
750
  const cleanFileKey = fileKey.replace(/[^a-zA-Z0-9-_]/g, '_');
754
- const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_:]/g, '_') : 'root';
751
+ const cleanNodeId = nodeId ? nodeId.replace(/[^a-zA-Z0-9-_]/g, '_') : 'root';
755
752
  const historyDir = path.join(this.workspaceRoot, '.sloth', cleanFileKey, cleanNodeId, 'history');
756
753
  try {
757
754
  const entries = await fs.readdir(historyDir, { withFileTypes: true });
@@ -1,5 +1,22 @@
1
1
  import { Logger } from './logger.js';
2
2
  import { getResourceMapAdvanced } from 'sloth-d2c-node/convert';
3
+ import { replacePathVariables } from './webpack-substitutions.js';
4
+ import { getSystemSupportFileName } from './utils.js';
5
+ import { sha1 } from 'js-sha1';
6
+ /**
7
+ * 移除 base64 字符串的前缀(如 data:image/png;base64,),只保留纯 base64 数据
8
+ * @param base64String 带前缀的 base64 字符串
9
+ * @returns 纯 base64 数据
10
+ */
11
+ export function removeBase64Prefix(base64String) {
12
+ if (!base64String)
13
+ return '';
14
+ const commaIndex = base64String.indexOf(',');
15
+ if (commaIndex !== -1) {
16
+ return base64String.slice(commaIndex + 1);
17
+ }
18
+ return base64String;
19
+ }
3
20
  /**
4
21
  * 检查imageSetting配置是否有变化,如果有变化则重新生成imageMap
5
22
  * @param currentImageMap 当前的imageMap
@@ -8,7 +25,36 @@ import { getResourceMapAdvanced } from 'sloth-d2c-node/convert';
8
25
  * @param newConfig 新的配置
9
26
  * @returns Promise<{ imageMap: any, updated: boolean }> - 返回新的imageMap和是否更新的标志
10
27
  */
11
- export async function updateImageMapIfNeeded(currentImageMap, imageNodeList, oldConfig, newConfig) {
28
+ export async function updateImageMapIfNeeded(currentImageMap, imageNodeList, oldConfig, newConfig, local) {
29
+ if (local) {
30
+ Logger.log('本地模式,直接更新imageMap');
31
+ for (let node of imageNodeList) {
32
+ const type = node.srcType === 'PNG' ? 'png' : 'svg';
33
+ const base64 = removeBase64Prefix(currentImageMap[node.id]?.base64);
34
+ const { imageStorageType, imageStorageNamingRule, imageStoragePath } = newConfig?.imageSetting;
35
+ if (imageStorageType === 'local') {
36
+ let webpackPathRule = imageStorageNamingRule;
37
+ if (!webpackPathRule.endsWith('.[ext]')) {
38
+ webpackPathRule += '.[ext]';
39
+ }
40
+ const name = replacePathVariables(webpackPathRule, {
41
+ filename: [getSystemSupportFileName(node.name), type].join('.'),
42
+ chunk: {
43
+ id: node.id,
44
+ name: getSystemSupportFileName(node.name),
45
+ contentHash: {
46
+ [type]: sha1(base64).substring(0, 8),
47
+ },
48
+ },
49
+ contentHashType: type,
50
+ }, undefined);
51
+ const path = [imageStoragePath, name].join('/');
52
+ node.src = path;
53
+ currentImageMap[node.id].path = path;
54
+ }
55
+ }
56
+ return { imageMap: currentImageMap, updated: true };
57
+ }
12
58
  // 提取相关的imageSetting配置项
13
59
  const oldImageSetting = oldConfig?.imageSetting || {};
14
60
  const newImageSetting = newConfig?.imageSetting || {};
@@ -29,10 +75,10 @@ export async function updateImageMapIfNeeded(currentImageMap, imageNodeList, old
29
75
  'imageStorageApiFileField',
30
76
  'imageStorageApiUrlField',
31
77
  'imageStorageApiCustomHeader',
32
- 'imageStorageApiCustomBody'
78
+ 'imageStorageApiCustomBody',
33
79
  ];
34
80
  // 检查是否有相关配置发生变化
35
- const hasImageSettingChanged = relevantKeys.some(key => {
81
+ const hasImageSettingChanged = relevantKeys.some((key) => {
36
82
  return oldImageSetting[key] !== newImageSetting[key];
37
83
  });
38
84
  if (!hasImageSettingChanged) {
@@ -40,7 +86,7 @@ export async function updateImageMapIfNeeded(currentImageMap, imageNodeList, old
40
86
  return { imageMap: currentImageMap, updated: false };
41
87
  }
42
88
  Logger.log('检测到imageSetting配置变化,重新生成imageMap');
43
- Logger.log('变化的配置项:', relevantKeys.filter(key => oldImageSetting[key] !== newImageSetting[key]));
89
+ Logger.log('变化的配置项:', relevantKeys.filter((key) => oldImageSetting[key] !== newImageSetting[key]));
44
90
  try {
45
91
  // 重新生成imageMap
46
92
  const newImageMap = await getResourceMapAdvanced(imageNodeList, newConfig);
@@ -1,18 +1,18 @@
1
1
  {
2
- "buildTime": "2025-12-22T09:27:54.770Z",
2
+ "buildTime": "2025-12-24T13:36:17.450Z",
3
3
  "mode": "build",
4
4
  "pages": {
5
5
  "main": {
6
6
  "file": "index.html",
7
- "size": 1628662,
8
- "sizeFormatted": "1.55 MB"
7
+ "size": 1642308,
8
+ "sizeFormatted": "1.57 MB"
9
9
  },
10
10
  "detail": {
11
11
  "file": "detail.html",
12
- "size": 281671,
13
- "sizeFormatted": "275.07 KB"
12
+ "size": 281799,
13
+ "sizeFormatted": "275.19 KB"
14
14
  }
15
15
  },
16
- "totalSize": 1910333,
17
- "totalSizeFormatted": "1.82 MB"
16
+ "totalSize": 1924107,
17
+ "totalSizeFormatted": "1.83 MB"
18
18
  }