|  | @@ -0,0 +1,103 @@
 | 
	
		
			
				|  |  | +const fs = require('fs');
 | 
	
		
			
				|  |  | +const path = require('path');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 定义要替换的目录
 | 
	
		
			
				|  |  | +const srcDir = path.join(__dirname, 'src');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 定义要搜索的文件扩展名
 | 
	
		
			
				|  |  | +const fileExtensions = ['.ts', '.html'];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 替换 picsum.photos 链接的函数
 | 
	
		
			
				|  |  | +function replacePicsumLinks(fileContent, filePath) {
 | 
	
		
			
				|  |  | +  let modifiedContent = fileContent;
 | 
	
		
			
				|  |  | +  let replacementCount = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 正则表达式匹配 picsum.photos 链接或不正确的 placeholder.com 链接
 | 
	
		
			
				|  |  | +  const picsumRegex = /(?:https:\/\/(?:fastly\.)?picsum\.photos\/id\/(\d+)(?:\/([^"'\s]+))?)|(?:https:\/\/via\.placeholder\.com\/(\d+)x(\d+)[^"']*?\?text=IMG)/g;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 为不同类型的图片生成不同的占位图颜色(使用十六进制格式)
 | 
	
		
			
				|  |  | +  const colors = {
 | 
	
		
			
				|  |  | +    avatar: ['FFCCCC', 'CCFFCC', 'CCCCFF', 'FFFFCC'],
 | 
	
		
			
				|  |  | +    image: ['F0F0F0', 'E6E6E6', 'DCDCDC'],
 | 
	
		
			
				|  |  | +    cover: ['C8C8C8', 'BABABA', 'B4B4B4']
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 替换匹配的链接
 | 
	
		
			
				|  |  | +  modifiedContent = modifiedContent.replace(picsumRegex, (match, id, sizePart, placeholderWidth, placeholderHeight) => {
 | 
	
		
			
				|  |  | +    // 解析图片尺寸
 | 
	
		
			
				|  |  | +    let width = 400;
 | 
	
		
			
				|  |  | +    let height = 300;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 如果是 placeholder 链接,直接使用提取的尺寸
 | 
	
		
			
				|  |  | +    if (placeholderWidth && placeholderHeight) {
 | 
	
		
			
				|  |  | +      width = parseInt(placeholderWidth);
 | 
	
		
			
				|  |  | +      height = parseInt(placeholderHeight);
 | 
	
		
			
				|  |  | +    } else if (sizePart) {
 | 
	
		
			
				|  |  | +      // 从 picsum 链接的尺寸部分提取尺寸信息
 | 
	
		
			
				|  |  | +      const sizeParts = sizePart.split('/').filter(Boolean);
 | 
	
		
			
				|  |  | +      if (sizeParts.length === 2) {
 | 
	
		
			
				|  |  | +        width = parseInt(sizeParts[0]);
 | 
	
		
			
				|  |  | +        height = parseInt(sizeParts[1]);
 | 
	
		
			
				|  |  | +      } else if (sizeParts.length === 1) {
 | 
	
		
			
				|  |  | +        // 如果只有一个尺寸值,使用它作为宽高
 | 
	
		
			
				|  |  | +        width = parseInt(sizeParts[0]);
 | 
	
		
			
				|  |  | +        height = parseInt(sizeParts[0]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 根据文件路径和图片ID决定使用哪种颜色
 | 
	
		
			
				|  |  | +    let colorType = 'image';
 | 
	
		
			
				|  |  | +    if (filePath.includes('avatar') || match.includes('/40/40') || match.includes('/48/48')) {
 | 
	
		
			
				|  |  | +      colorType = 'avatar';
 | 
	
		
			
				|  |  | +    } else if (match.includes('/600/400') || match.includes('/800/600')) {
 | 
	
		
			
				|  |  | +      colorType = 'cover';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 选择一个颜色(基于ID的哈希值或随机值)
 | 
	
		
			
				|  |  | +    const colorIndex = id ? parseInt(id) % colors[colorType].length : Math.floor(Math.random() * colors[colorType].length);
 | 
	
		
			
				|  |  | +    const color = colors[colorType][colorIndex];
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    replacementCount++;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // 返回正确格式的 placeholder.com 链接
 | 
	
		
			
				|  |  | +    return `https://via.placeholder.com/${width}x${height}/${color}/555555?text=IMG`;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return { modifiedContent, replacementCount };
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 遍历目录中的文件
 | 
	
		
			
				|  |  | +function traverseDirectory(dir) {
 | 
	
		
			
				|  |  | +  const files = fs.readdirSync(dir);
 | 
	
		
			
				|  |  | +  let totalReplacements = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  files.forEach(file => {
 | 
	
		
			
				|  |  | +    const filePath = path.join(dir, file);
 | 
	
		
			
				|  |  | +    const stat = fs.statSync(filePath);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (stat.isDirectory()) {
 | 
	
		
			
				|  |  | +      const subDirReplacements = traverseDirectory(filePath);
 | 
	
		
			
				|  |  | +      totalReplacements += subDirReplacements;
 | 
	
		
			
				|  |  | +    } else if (fileExtensions.some(ext => file.endsWith(ext))) {
 | 
	
		
			
				|  |  | +      // 读取文件内容
 | 
	
		
			
				|  |  | +      const fileContent = fs.readFileSync(filePath, 'utf8');
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      // 替换 picsum.photos 链接
 | 
	
		
			
				|  |  | +      const { modifiedContent, replacementCount } = replacePicsumLinks(fileContent, filePath);
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      // 如果有替换,写入文件
 | 
	
		
			
				|  |  | +      if (replacementCount > 0) {
 | 
	
		
			
				|  |  | +        fs.writeFileSync(filePath, modifiedContent, 'utf8');
 | 
	
		
			
				|  |  | +        console.log(`已替换 ${filePath} 中的 ${replacementCount} 个图片链接`);
 | 
	
		
			
				|  |  | +        totalReplacements += replacementCount;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return totalReplacements;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 执行替换操作
 | 
	
		
			
				|  |  | +console.log('开始替换 picsum.photos 链接...');
 | 
	
		
			
				|  |  | +const totalReplacements = traverseDirectory(srcDir);
 | 
	
		
			
				|  |  | +console.log(`替换完成!总共替换了 ${totalReplacements} 个图片链接。`);
 |