NEXT主题博客图片引用的通用解决方案

💡 本文对以下场景有所帮助

  • 适用于NEXT主题的博客图片引用方式

背景介绍

写博客的时候,图片引用这里踩了不少坑,现在总结一下。

时间顺序

1. 最基本的引用

在博客中使用以下方式可以对图片进行引用

1
![](/2024/06/05/维修报告/NEXT主题博客图片引用的通用解决方案/1.png)

效果如下

推荐使用Typora+Snipaste,直接在markdown复制过来即可将图片复制到对应的文件夹,不需要修改任何的文本内容。

如果你在hexo new “博客名称”的时候没有创建对应的文件夹,那你需要要将_config.yml中的post_asset_folder设置成true

1
post_asset_folder: true

2. 博客展示

这种展示方式虽然能够在本地展示图片,但是在执行hexo s或者hexo d运行的时候,会导致显示图片加载失败。这是因为在最终部署网站的时候,博客是根据创建时间进行去对每一篇post进行分类。

因此,如果你希望能够在网站界面上显示的话,以当前的博客为例,这篇博客的创建日期是2024年6月5号,并且它的路径在”/项目名称/source/_posts”下面,那你的图片路径应该修改成以下内容

1
![](/2024/06/05/NEXT主题博客图片引用的通用解决方案/1.png)

3. 层级结构

由于文章越来越多,我们需要对文件的路径进行管理。为了保证图片能够正常引用,我们需要将博客本身(md文件)和其对应的文件夹放在同一个路径下面。

一个合理的层级结构如下所示,这里覆盖了所有的层次结构,分别是不嵌套、一层嵌套和多层嵌套。

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
➜  test tree
.
└── source
└── _posts
├── 在MacOS删除Word中的Mendeley
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ └── 5.png
├── 在MacOS删除Word中的Mendeley.md
└── 小玩具
├── Create-Your-Own-Discord-Bot
│ ├── 1.png
│ ├── 10.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ └── 9.png
├── Create-Your-Own-Discord-Bot.md
├── Upgrade-Official-Odoo12-Image-From-py3-5-To-py3-8
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── Dockerfile
│ └── requirements.txt
├── Upgrade-Official-Odoo12-Image-From-py3-5-To-py3-8.md
└── 大乐趣
├── A-Web-502-Error-Caused-By-A-Docker-Upgrade
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ └── 9.png
└── A-Web-502-Error-Caused-By-A-Docker-Upgrade.md

9 directories, 33 files
➜ test

不同嵌套结构下的图片引用的路径也需要做相应的修改

1
2
3
4
5
6
7
8
9
10
11
File: ./source/_posts/在MacOS删除Word中的Mendeley.md
![](/2024/01/26/在MacOS删除Word中的Mendeley/1.png)

File: ./source/_posts/小玩具/Create-Your-Own-Discord-Bot.md
![](/2023/04/17/小玩具/Create-Your-Own-Discord-Bot/1.png)

File: ./source/_posts/小玩具/Upgrade-Official-Odoo12-Image-From-py3-5-To-py3-8.md
![](/2023/03/08/小玩具/Upgrade-Official-Odoo12-Image-From-py3-5-To-py3-8/1.png)

File: ./source/_posts/小玩具/大乐趣/A-Web-502-Error-Caused-By-A-Docker-Upgrade.md
![](/2023/03/16/小玩具/大乐趣/A-Web-502-Error-Caused-By-A-Docker-Upgrade/1.png)

4. 图片本地引用地址和部署地址的切换

我们需要在本地写博客的时候显示图片,又需要在部署的时候显示图片,这就涉及到不同场景下图片引用地址之间的转变。

在这里,我编写了一个python的转变脚本,通过制定不同场景的参数,就能够实现图片引用地址的转变。转变效果如下所示。

代码如下所示

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
82
83
84
85
86
87
88
89
90
91
92
'''
Author: Simon
Date: 2024-01-26 01:27:57
LastEditors: Simon
LastEditTime: 2024-06-05 23:24:57
Description: update blog picture address according to the situation
'''
import os
import re
import sys

def find_and_replace_images(directory, action):
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".md"):
file_path = os.path.join(root, file)
process_file(file_path, action)

def process_file(file_path, action):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.readlines()

relative_dir = os.path.dirname(os.path.relpath(file_path, start='./source/_posts'))
blog_name = os.path.splitext(os.path.basename(file_path))[0]
date_line = next((line for line in content if line.startswith('date: ')), None)
if date_line:
creation_date = extract_date(date_line)
modified_content, changes_made, changes_detail = modify_content(content, action, blog_name, creation_date, relative_dir)

if changes_made:
with open(file_path, 'w', encoding='utf-8') as file:
file.writelines(modified_content)
print(f"Updated file: {file_path}")
for detail in changes_detail:
print(f" Line {detail['line']}: {detail['original']} -> {detail['modified']}")
print( " ...\n")
break
else:
# print(f"No changes made to: {file_path}")
pass
else:
# print(f"No date line found in: {file_path}")
pass

def extract_date(date_line):
match = re.search(r'\d{4}-\d{2}-\d{2}', date_line)
if match:
return match.group().replace('-', '/')
return None

def modify_content(content, action, blog_name, creation_date, relative_dir):
changes_made = False
changes_detail = []

image_pattern = re.compile(r"!\[\]\(" + re.escape(blog_name) + r"/([^)]+)\)")
link_pattern = re.compile(r"\]\(" + re.escape(blog_name) + r"/([^)]+)\)")

for i, line in enumerate(content):
original_line = line
if action == "--upload" and creation_date:
if relative_dir:
line = image_pattern.sub(f"![](/{creation_date}/{relative_dir}/{blog_name}/\\1)", line)
line = link_pattern.sub(f"](/{creation_date}/{relative_dir}/{blog_name}/\\1)", line)
else:
line = image_pattern.sub(f"![](/{creation_date}/{blog_name}/\\1)", line)
line = link_pattern.sub(f"](/{creation_date}/{blog_name}/\\1)", line)
elif action == "--local":
if creation_date:
if relative_dir:
line = re.sub(r"!\[\]\(/" + re.escape(creation_date) + "/" + re.escape(relative_dir) + "/" + re.escape(blog_name) + r"/([^)]+)\)", f"![]({blog_name}/\\1)", line)
line = re.sub(r"\]\(/" + re.escape(creation_date) + "/" + re.escape(relative_dir) + "/" + re.escape(blog_name) + r"/([^)]+)\)", f"]({blog_name}/\\1)", line)
else:
line = re.sub(r"!\[\]\(/" + re.escape(creation_date)+ "/" + re.escape(blog_name) + r"/([^)]+)\)", f"![]({blog_name}/\\1)", line)
line = re.sub(r"\]\(/" + re.escape(creation_date) + "/" + re.escape(blog_name) + r"/([^)]+)\)", f"]({blog_name}/\\1)", line)

if line != original_line:
changes_made = True
changes_detail.append({'line': i+1, 'original': original_line.strip(), 'modified': line.strip()})
content[i] = line

return content, changes_made, changes_detail

if __name__ == "__main__":
directory = './source/_posts'

if len(sys.argv) != 2 or sys.argv[1] not in ["--local", "--upload"]:
print("Usage: python script.py --local | --upload")
sys.exit(1)

action = sys.argv[1]
find_and_replace_images(directory, action)