该页面由AI翻译并经过人工校对,你可能想要
查看原文
前言
由于 post_asset_folder 在 _config.yml 文件中的设置如下,因此每篇文章的资源都可以在与文章同名的目录中找到。
1 2 3 4
| post_asset_folder: true marked: prependRoot: true postAsset: true
|
然而,在本网站支持国际化之后,冗余资源会大量积累。不同语言的文章内容应该不同,但资源应该相同。以下是源文件的目录结构。不同语言中带有 (*) 的资源目录是重复的,可以进行优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| source ├── _posts │ ├── en │ │ └── 2025 │ │ ├── 07 │ │ │ ├── online-404-error-troubleshooting (*) │ │ │ └── online-404-error-troubleshooting.md │ │ └── 08 │ │ ├── exploring-multilingual-site-solutions-in-hexo (*) │ │ └── exploring-multilingual-site-solutions-in-hexo.md │ └── zh-CN │ └── 2025 │ ├── 07 │ │ ├── online-404-error-troubleshooting (*) │ │ └── online-404-error-troubleshooting.md │ └── 08 │ ├── exploring-multilingual-site-solutions-in-hexo (*) │ └── exploring-multilingual-site-solutions-in-hexo.md ├── en │ ├── 404 │ ├── about │ ├── albums │ │ ├── animal │ │ │ ├── cat (*) │ │ │ ├── cat.md │ │ │ ├── dog (*) │ │ │ ├── dog.md │ │ │ └── index.md │ │ └── index.md │ ├── categories │ └── tags └── zh-CN ├── 404 ├── about ├── albums │ ├── animal │ │ ├── cat (*) │ │ ├── cat.md │ │ ├── dog (*) │ │ ├── dog.md │ │ └── index.md │ └── index.md ├── categories └── tags
|
优化
设计
首先,为了减少之前对资源引用方式的影响,我需要设计静态资源的组织方式。幸运的是,只需将所有重复的资源目录移动到 /source/images 目录(带有 (*) 的目录)即可,如下所示。之后,如果使用相对路径引用资源,只需进行少量更改即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| . ├── _posts │ ├── en │ │ └── 2025 │ │ ├── 07 │ │ │ └── online-404-error-troubleshooting.md │ │ └── 08 │ │ └── exploring-multilingual-site-solutions-in-hexo.md │ └── zh-CN │ └── 2025 │ ├── 07 │ │ └── online-404-error-troubleshooting.md │ └── 08 │ └── exploring-multilingual-site-solutions-in-hexo.md ├── en │ ├── 404 │ ├── about │ ├── albums │ │ ├── animal │ │ │ ├── cat.md │ │ │ ├── dog.md │ │ │ └── index.md │ │ └── index.md │ ├── categories │ └── tags ├── images │ ├── 2025 │ │ ├── 07 │ │ │ └── online-404-error-troubleshooting (*) │ │ └── 08 │ │ └── exploring-multilingual-site-solutions-in-hexo (*) │ ├── albums │ │ └── animal │ │ ├── cat (*) │ │ └── dog (*) │ ├── my_avatar.png │ └── my_favicon.png └── zh-CN ├── 404 ├── about ├── albums │ ├── animal │ │ ├── cat.md │ │ ├── dog.md │ │ └── index.md │ └── index.md ├── categories └── tags
|
然后,找到一种方法来替换每篇帖子中引用的资源路径。由于资源可以通过相对路径或绝对路径(以 http、https 或 / 开头)引用,如果是绝对路径,则直接使用该路径;否则,在 /images 目录中与帖子同名的目录中查找资源。因此,只需将相对路径转换为 /images/[prefix]/[name]/[resource],其中 name 表示帖子名称,resource 表示资源名称,prefix 表示从 /source/[lang] 到帖子的路径。
例如,对于帖子 /2025/07/my-post.md,无论语言是什么。
- 如果资源引用为 ./image.png,则资源路径将转换为 /images/2025/07/my-post/image.png。在本例中,prefix 为 2025/07,name 为 my-post,resource 为 image.png。 注意 如果您使用相对路径,请确保它始终以 './' 开头。如果您使用 ../another-post/image.png,它将不会被转换为 /images/2025/07/another-post/image.png。如果您确实需要使用属于其他帖子的资源,请尝试使用绝对路径,例如 /images/2025/07/another-post/image.png。
- 如果资源被引用为 /images/2025/07/my-post/image.png,由于它是绝对路径,因此资源路径不会被转换。
- 如果资源被引用为 https://exmaple.com/image.png,资源路径也不会被转换。
更多示例请参见下文。
实现
在 themes/arch/scripts 目录下创建一个名为 hexo-filter.js 的文件,并输入以下代码。在 after_post_rende 的回调中,可以访问所有数据,包括原始内容、解析后的内容以及页面元信息。获取所有 <img>
的 src 值,如果 src 是相对路径,则应用上述路径转换。就是这样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| const absPathRegExp = /^(https?:\/\/|\/)/i;
function replaceRelativePath(src, prefix) { if (absPathRegExp.test(src)) { return src; } let cleanSrc = src.replace(/^(\.\/|\.\.\/)+/, "");
return [prefix, cleanSrc].join("/"); }
hexo.extend.filter.register("after_post_render", function (data) { const { source, type } = data;
if (["tags", "categories"].includes(type)) { return data; }
const parts = source.split("/");
let dirParts = !type ? parts.slice(2, -1) : parts.slice(1, -1); if (!type || type === "album") { dirParts = dirParts.concat(parts[parts.length - 1].replace(/\.md$/, "")); }
const prefix = `/images/${dirParts.join("/")}`;
data.content = data.content.replace( /<img\s+([^>]*?)src=["']([^"']+)["']([^>]*?)>/gi, function (match, pre, src, post) { if (absPathRegExp.test(src)) { return match; } return `<img ${pre}src="${replaceRelativePath(src, prefix)}"${post}>`; } );
if (type === "albums" && Array.isArray(data.children)) { data.children.forEach((child) => { if (child.cover) { child.cover = replaceRelativePath(child.cover, prefix); } }); }
if (type === "album" && Array.isArray(data.resources)) { data.resources.forEach((resource) => { if (resource.src) { resource.src = replaceRelativePath(resource.src, prefix); } }); } return data; });
|
使用方法
如果在文章中使用 <img />
以相对路径引用资源,则无需执行任何操作。对于相册和相册类型页面,由于存在绝对路径,因此需要进行如下更改。
请注意,只有使用 <img />
以相对路径引用资源时,才会转换资源路径。核心逻辑如下。
1 2 3 4 5 6 7 8 9 10 11
| data.content = data.content.replace( /<img\s+([^>]*?)src=["']([^"']+)["']([^>]*?)>/gi, function (match, pre, src, post) { if (absPathRegExp.test(src)) { return match; } return `<img ${pre}src="${replaceRelativePath(src, prefix)}"${post}>`; } );
|
如果您使用 Markdown 语法或 Hexo 标签使用相对路径(如下所示),资源路径将不会被转换,图片将加载失败。
1 2 3
| 
{% asset_img "image.png" "image.png" %}
|