diff --git a/package.json b/package.json
index 3de0b11d7..bbc88dc6e 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"type-check": "tsc --noEmit --isolatedDeclarations",
"new-post": "node scripts/new-post.js",
"clean": "node scripts/clean-unused-images.js",
+ "del-space": "node scripts/del-space.js",
"format": "biome format --write ./src",
"lint": "biome check --write ./src"
},
diff --git a/scripts/del-space.js b/scripts/del-space.js
new file mode 100644
index 000000000..fb09c7195
--- /dev/null
+++ b/scripts/del-space.js
@@ -0,0 +1,312 @@
+#!/usr/bin/env node
+
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+import { glob } from "glob";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const CONTENT_DIR = path.join(process.cwd(), "src/content");
+const POSTS_DIR = path.join(CONTENT_DIR, "posts");
+
+/**
+ * 获取所有 markdown 文件
+ */
+async function getAllMarkdownFiles() {
+ try {
+ const pattern = path.join(POSTS_DIR, "**/*.md").replace(/\\/g, "/");
+ return await glob(pattern);
+ } catch (error) {
+ console.error("获取 markdown 文件失败:", error.message);
+ return [];
+ }
+}
+
+/**
+ * 处理单个 Markdown 文件
+ */
+async function processMarkdownFile(filePath) {
+ let content = fs.readFileSync(filePath, "utf-8");
+ let originalContent = content;
+ let hasChanges = false;
+ let changedCount = 0;
+
+ const replacements = [];
+
+ // 1. 处理 YAML frontmatter 中的 image 字段
+ const yamlImageRegex = /^---[\s\S]*?image:\s*(?:['"]([^'"]+)['"]|([^\s\n]+))[\s\S]*?^---/m;
+ let match = yamlImageRegex.exec(content);
+ if (match) {
+ const fullMatch = match[0];
+ // 捕获组1是带引号的,捕获组2是不带引号的
+ const imagePath = match[1] || match[2];
+
+ if (imagePath && (imagePath.includes(" ") || imagePath.includes("%20") || imagePath.includes(",") || hasExtraDots(imagePath))) {
+ // 当路径包含空格、%20、逗号或额外点时处理
+ const result = await handleImageRename(filePath, imagePath);
+ if (result) {
+ // 替换 YAML 中的路径
+ // 注意:这里需要小心替换,只替换 image: 后的部分
+ // 简单起见,我们对整个 content 做字符串替换,但要注意唯一性
+ // 更稳妥的方式是替换 match[0] 中的 imagePath
+
+ // 这里我们先收集替换信息,最后统一替换,或者直接替换 content
+ // 为了防止多次替换导致错乱,我们记录下来
+ replacements.push({
+ original: imagePath,
+ new: result
+ });
+ }
+ }
+ }
+
+ // 2. 处理 Markdown 图片语法 
+ const markdownImageRegex = /!\[.*?\]\((.*?)\)/g;
+ while ((match = markdownImageRegex.exec(content)) !== null) {
+ const fullUrl = match[1];
+ // 去除可能的 title 部分
+ let url = fullUrl;
+ const titleMatch = url.match(/^(\S+)\s+["'].*["']$/);
+ if (titleMatch) {
+ url = titleMatch[1];
+ }
+
+ // 去除 <> 包裹
+ if (url.startsWith('<') && url.endsWith('>')) {
+ url = url.slice(1, -1);
+ }
+
+ if (url.includes(" ") || url.includes("%20") || url.includes(",") || hasExtraDots(url)) {
+ const result = await handleImageRename(filePath, url);
+ if (result) {
+ replacements.push({
+ original: url, // 这里需要替换的是原始引用的 url 部分 (不含 title)
+ new: result,
+ fullMatch: fullUrl // 也可以用于定位
+ });
+ }
+ }
+ }
+
+ // 3. 处理 HTML img 标签
+ const htmlImageRegex = /
]+src=["']([^"']+)["'][^>]*>/gi;
+ while ((match = htmlImageRegex.exec(content)) !== null) {
+ const url = match[1];
+ if (url.includes(" ") || url.includes("%20") || url.includes(",") || hasExtraDots(url)) {
+ const result = await handleImageRename(filePath, url);
+ if (result) {
+ replacements.push({
+ original: url,
+ new: result
+ });
+ }
+ }
+ }
+
+ // 执行替换
+ if (replacements.length > 0) {
+ // 按照 original 长度倒序排序,避免部分替换
+ replacements.sort((a, b) => b.original.length - a.original.length);
+
+ // 去重
+ const uniqueReplacements = new Map();
+ replacements.forEach(item => {
+ if (!uniqueReplacements.has(item.original)) {
+ uniqueReplacements.set(item.original, item.new);
+ }
+ });
+
+ for (const [original, newPath] of uniqueReplacements) {
+ // 全局替换
+ // 需要转义正则特殊字符
+ const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ const regex = new RegExp(escapedOriginal, 'g');
+
+ if (content.match(regex)) {
+ content = content.replace(regex, newPath);
+ hasChanges = true;
+ changedCount++;
+ console.log(` 🔄 更新引用: "${original}" -> "${newPath}"`);
+ }
+ }
+ }
+
+ if (hasChanges) {
+ fs.writeFileSync(filePath, content, "utf-8");
+ console.log(`💾 已保存文件: ${path.relative(process.cwd(), filePath)} (更新了 ${changedCount} 处引用)`);
+ }
+}
+
+/**
+ * 处理图片重命名
+ * @returns {string|null} 新的相对路径,如果没有变化或失败则返回 null
+ */
+async function handleImageRename(markdownPath, imagePath) {
+ // 1. 解析绝对路径
+ let absolutePath = null;
+ const markdownDir = path.dirname(markdownPath);
+
+ // 解码 URL (处理 %20)
+ let decodedPath = imagePath;
+ try {
+ decodedPath = decodeURIComponent(imagePath);
+ } catch (e) {
+ // ignore
+ }
+
+ if (decodedPath.startsWith("http://") || decodedPath.startsWith("https://")) {
+ return null;
+ }
+
+ if (decodedPath.startsWith("/")) {
+ // 绝对路径,通常相对于 public 或 src (这里假设是 src/content/assets 或者 public)
+ // Fuwari 项目结构似乎图片在 src/content/assets
+ // 如果以 / 引用,可能很难确定根目录,暂且跳过,除非它是相对于 content 的
+ // 观察现有代码,normalizePath 忽略了 / 开头的。
+ // 但用户提到 "寻找MarkDown中的相对路径的图片",所以我们可以只关注相对路径
+ return null;
+ } else {
+ // 相对路径
+ absolutePath = path.resolve(markdownDir, decodedPath);
+ }
+
+ if (!fs.existsSync(absolutePath)) {
+ console.warn(` ⚠️ 图片不存在 (跳过): ${decodedPath}`);
+ return null;
+ }
+
+ // 2. 生成新文件名 (删除空格、逗号、以及除了扩展名点之外的其他点)
+ const dir = path.dirname(absolutePath);
+ const filename = path.basename(absolutePath);
+ const ext = path.extname(filename);
+ const nameWithoutExt = path.basename(filename, ext);
+
+ // 移除空格、%20、逗号、以及点
+ const newName = nameWithoutExt
+ .replace(/\s+/g, "")
+ .replace(/%20/g, "")
+ .replace(/,/g, "")
+ .replace(/\./g, ""); // 移除文件名主体中的所有点
+
+ const newFilename = newName + ext;
+
+ if (filename === newFilename) {
+ return null; // 没有变化
+ }
+
+ const newAbsolutePath = path.join(dir, newFilename);
+
+ // 3. 重命名文件
+ try {
+ if (fs.existsSync(newAbsolutePath)) {
+ // 如果目标文件已存在
+ // 比较内容是否一致?或者直接覆盖?或者跳过?
+ // 简单起见,如果目标存在且不是同一个文件(虽然文件名不同,但在某些不区分大小写系统可能冲突,不过这里是去除空格,应该不同)
+ // 假设用户希望合并
+ console.warn(` ⚠️ 目标文件已存在: ${path.basename(newAbsolutePath)} (将使用已存在的文件)`);
+ // 如果源文件存在,删除源文件 (因为它被合并到了目标文件)
+ // 但为了安全,也许我们不应该删除,只是更新引用?
+ // 还是说:如果A.png和A .png都存在,我们将A .png重命名为A.png,这会覆盖A.png吗?
+ // fs.renameSync 会覆盖。
+ // 既然是"del-space",如果去空格后的文件已存在,说明可能已经有一份了。
+ // 我们可以认为它们是同一张图(或者用户不介意),直接使用新文件名,并保留(或覆盖)
+
+ // 安全起见,如果目标存在,我们不覆盖,只是更新引用指向它。
+ // 但是源文件怎么办?如果不删除,就是"clean"脚本的事了。
+ // 用户说 "同步修改原图的文件名",implies rename.
+ // 如果我 rename A to B, and B exists. rename fails or overwrites.
+ // 让我们尝试 rename,如果报错再处理.
+ } else {
+ fs.renameSync(absolutePath, newAbsolutePath);
+ console.log(` ✨ 重命名图片: "${filename}" -> "${newFilename}"`);
+ }
+ } catch (error) {
+ console.error(` ❌ 重命名失败: ${error.message}`);
+ return null;
+ }
+
+ // 4. 返回新的相对路径
+ // 保持原来的相对路径结构,只改变文件名
+ // imagePath 可能是 ../assets/foo bar.png
+ // 我们需要返回 ../assets/foobar.png
+
+ // 重新构建引用路径
+ // 使用 path.dirname(imagePath) 可能会受到 OS 分隔符影响
+ // 我们简单地替换文件名
+
+ // 注意:imagePath 可能是 encoded 的 (%20),也可能是 raw space
+ // 我们返回的新路径应该是不包含空格的,通常不需要 encode
+
+ // 获取 imagePath 的目录部分
+ // 简单的字符串操作:找到最后一个 / 或 \
+ const lastSeparatorIndex = Math.max(imagePath.lastIndexOf('/'), imagePath.lastIndexOf('\\'));
+ let newReferencePath;
+ if (lastSeparatorIndex === -1) {
+ newReferencePath = newFilename;
+ } else {
+ newReferencePath = imagePath.substring(0, lastSeparatorIndex + 1) + newFilename;
+ }
+
+ return newReferencePath;
+}
+
+/**
+ * 检查路径中是否包含除了扩展名点之外的其他点(仅检查文件名部分)
+ */
+function hasExtraDots(imagePath) {
+ try {
+ // 解码
+ let decodedPath = imagePath;
+ try {
+ decodedPath = decodeURIComponent(imagePath);
+ } catch (e) {
+ // ignore
+ }
+
+ // 获取文件名
+ const filename = path.basename(decodedPath);
+
+ // 如果是以点开头的文件(如 .gitignore),忽略
+ if (filename.startsWith('.')) {
+ // 如果只有开头的点,没有其他点,则是 false
+ // 如果有其他点,如 .foo.bar,则是 true
+ const parts = filename.split('.');
+ return parts.length > 2;
+ }
+
+ // 正常文件名
+ const ext = path.extname(filename);
+ const nameWithoutExt = path.basename(filename, ext);
+
+ // 检查 nameWithoutExt 是否包含点
+ return nameWithoutExt.includes('.');
+ } catch (error) {
+ return false;
+ }
+}
+
+async function main() {
+ console.log("🔍 开始扫描 Markdown 文件中的空格图片路径...");
+
+ if (!fs.existsSync(POSTS_DIR)) {
+ console.error(`❌ Posts 目录不存在: ${POSTS_DIR}`);
+ return;
+ }
+
+ const files = await getAllMarkdownFiles();
+ console.log(`📄 找到 ${files.length} 个 Markdown 文件`);
+
+ for (const file of files) {
+ // console.log(`检查: ${path.relative(process.cwd(), file)}`);
+ await processMarkdownFile(file);
+ }
+
+ console.log("✅ 完成!");
+}
+
+main().catch(err => {
+ console.error("❌ 发生错误:", err);
+ process.exit(1);
+});
diff --git a/src/content/assets/images/Mermaid Chart - Create complex, visual diagrams with text.-2026-01-09-031619.png b/src/content/assets/images/MermaidChart-Createcomplexvisualdiagramswithtext-2026-01-09-031619.png
similarity index 100%
rename from src/content/assets/images/Mermaid Chart - Create complex, visual diagrams with text.-2026-01-09-031619.png
rename to src/content/assets/images/MermaidChart-Createcomplexvisualdiagramswithtext-2026-01-09-031619.png
diff --git a/src/content/assets/images/msedge_HwStEUKYVx 1.gif b/src/content/assets/images/msedge_HwStEUKYVx1.gif
similarity index 100%
rename from src/content/assets/images/msedge_HwStEUKYVx 1.gif
rename to src/content/assets/images/msedge_HwStEUKYVx1.gif
diff --git a/src/content/assets/images/屏幕截图 2025-08-09 213908.png b/src/content/assets/images/屏幕截图2025-08-09213908.png
similarity index 100%
rename from src/content/assets/images/屏幕截图 2025-08-09 213908.png
rename to src/content/assets/images/屏幕截图2025-08-09213908.png
diff --git a/src/content/posts/WPwebplayer.md b/src/content/posts/WPwebplayer.md
index aa1d26d8a..3ef70303f 100644
--- a/src/content/posts/WPwebplayer.md
+++ b/src/content/posts/WPwebplayer.md
@@ -2,7 +2,7 @@
title: 【开源】WPwebplayer——简洁通用的网页播放器
published: 2025-08-09
description: '一款简单,简洁,轻量,通用的开源网站音乐播放器'
-image: '../assets/images/屏幕截图 2025-08-09 213908.png'
+image: '../assets/images/屏幕截图2025-08-09213908.png'
tags: [Web]
category: '记录'
draft: false
diff --git a/src/content/posts/shorter-url.md b/src/content/posts/shorter-url.md
index 7c9ca960a..b746b62af 100644
--- a/src/content/posts/shorter-url.md
+++ b/src/content/posts/shorter-url.md
@@ -31,5 +31,5 @@ Cloudflare Page/Worker的重定向文件提供了基于文件的重定向功能
# 服务架构图
-
+
diff --git a/src/content/posts/uptimeflare.md b/src/content/posts/uptimeflare.md
index 0dd47e656..7356ca097 100644
--- a/src/content/posts/uptimeflare.md
+++ b/src/content/posts/uptimeflare.md
@@ -46,7 +46,7 @@ lang: ""
首先,我们先尝试将其部署到Cloudflare
创建一个Cloudflare API Token **编辑Workers** 和 **D1**
-
+
接下来将该Token绑定到你的Github仓库
