起因 | 兼容问题

我在使用渐构官网的导出HTML文件,发现与我正在使用的博客框架Hexo对Markdown的处理并不一样,这让渐构官网的导出HTML文件不兼容我的博客的显示。

更新流程 Markdown原理

由于难以更改渐构官网和Hexo框架的代码,所以我对流程进行了一定的改变。

原先流程:

flowchart LR
     Evoldown文件 -- 官网直出 --> HTML文件;
     HTML文件-- Hexo解析器 --> HTML页面显示异常;

现在流程:

flowchart LR
     Evoldown文件 -- evoldown-to-markdown(本地脚本) --> Markdown文件; 
     Markdown文件 -- Hexo解析器 --> HTML页面文件;

通过参考Markdown原理,我通过Python代码将Evoldown转换成符合一般规范的Markdown,然后再使用其他第三方的Markdown转HTML工具进行处理,以此解决往后会发生的兼容问题。

同时,也可以利用这次的实践,学习如何用代码开发对文本处理的工具。

Markdown原理

就像Markdown作者博客上说的:

“Markdown”是两件事:(1)纯文本格式语法; (2)用Perl编写的软件工具,用于转换纯文本 格式化为 HTML。

Markdown一般规范

Markdown作者
https://daringfireball.net/projects/markdown

Markdown爱好者(通用规范)
https://commonmark.org/
https://commonmark.org/help/

 GitHub Flavored Markdown
https://docs.github.com/zh/get-started/writing-on-github
https://github.github.com/gfm/

关于Evoldown

官网示例: https://www.modevol.com/evoldown

个人整理: https://www.modevol.com/document/jh19i7n3uj2zfwl03nn9c7i9

代码展示
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# 引入正则表达式库  
import re
# 引入系统操作库
import os
# 引入lxml处理svg代码
from lxml import etree
# 引入模板引擎
from jinja2 import Template

# 定义段落类型与对应svg图标的映射关系
icon_svg_filename = {
'#d': 'Description',
'#e': 'Example',
'#t': 'Transfer',
'#c': 'Custom',
'#v': 'Verification',
'#a': 'Advertisement'
}

# 定义段落svg图标的参数
icon_svg_changes = {
'fill': 'currentColor', # 使用当前文字的颜色填充
'width': '2em', # 宽度是文字大小的两倍
'height': '2em' # 高度是文字大小的两倍
}

# 定义段落类型与对应hsl()颜色的映射关系
card_color = {
'#d': '200 72% 50%',
'#e': '0 72% 50%',
'#t': '50 72% 50%',
'#c': '0 0% 50%',
'#v': '260 72% 50%',
'#a': '300 72% 50%'
}


# f-string 是 Python3.6 引入的一种新的字符串格式化方式,
# 它允许在字符串中插入变量值或表达式结果,
# 使用 {} 括起来,并在字符串前面加上 f 或 F。
# 获取本项目svg文件夹里的SVG图标的源代码,并更改样式
def extract_modify_svg_content(svg_filename, svg_changes):
"""
从SVG文件中提取并修改内容。

Parameters: svg_filename (str): SVG文件名。
svg_changes: 变化参数

Returns: str_content: 修改后的SVG内容。

""" # 构建SVG文件的路径
svg_path = os.path.join('svg', f'{svg_filename}.svg')
# 打开SVG文件并读取内容
with open(svg_path, 'r', encoding='utf-8') as svg_file:
svg_code = svg_file.read()
# 将 Unicode 字符串转换为字节字符串
svg_bytes = svg_code.encode('utf-8')
# 使用 lxml 解析 SVG 文件
svg_root = etree.fromstring(svg_bytes)
# 修改svg的属性
for key, value in svg_changes.items():
svg_root.attrib[key] = value
# 获取 <svg> 标签内的内容
svg_content = etree.tostring(svg_root, encoding="unicode")
return svg_content


# 该函数的输入参数是evoldown文件的位置和输出的markdown文件位置
def convert_evoldown_to_markdown(evoldown_file, markdown_file):
"""
将Evoldown格式转换为Markdown格式。

Parameters: evoldown_file (str): 输入的Evoldown文件位置。
markdown_file (str): 输出的Markdown文件位置。
""" # 以utf-8格式读取evoldown文件给file对象,然后把内容保存到evoldown_text里面,
with open(evoldown_file, 'r', encoding='utf-8') as input_file:
evoldown_text = input_file.read()
# print(evoldown_text)

# 识别标签语法

# raw string 是一种特殊的字符串,它以 r 或 R 开头,并且对反斜杠 \ 不进行转义处理。
# 正则表达式匹配:学习材料的类型,学习材料的关键词,关联的学习材料。
pattern = r'(#[detva])( \S+)( \S+)?'
# 正则表达式匹配:学习材料的类型、自定义的学习材料的类型、学习材料的关键词、关联的学习材料。
pattern_c = r'(#c)( \S+)( \S+)( \S+)?'

# 提取根据表达式提取内容
matches = re.findall(pattern, evoldown_text)
matches_c = re.findall(pattern_c, evoldown_text)

# 创建字典方便根据关键词寻找类型
dict_matches = {}
dict_matches_c = {}
# 遍历 matches,将关键词和材料类型添加到字典中
for match in matches:
material_type, keywords, associated_keyword = match
dict_matches[keywords] = material_type
# 遍历 matches_c,将关键词、材料类型和自定义类型添加到字典中
for match_c in matches_c:
material_type, custom_type, keywords, associated_keyword = match_c
dict_matches_c[keywords] = [material_type, custom_type]

# print(matches)
# print(matches_c) # print(dict_matches) # print(dict_matches_c)
# 查询的函数实现
def find_associated_type(key):
# 首先在 dict_matches 中查找关键字
if key in dict_matches:
return [dict_matches[key], None]
# 如果在 dict_matches 中未找到,则在 dict_matches_c 中查找
elif key in dict_matches_c:
return dict_matches_c[key]

# 段落文本标记替换成HTML代码
new_markdown_text = evoldown_text

# 定义段落标记 HTML 模板
tag_html_template = """
<div style="display: flex; flex-direction: row; align-items: center;">
{{ material_card }}
{{ find_associated_svg }}
{{ associated_card }}
</div>
""" # 定义卡片 HTML 模板
card_html_template = """<span style="display: flex; flex-direction: row; align-items: center; color: hsl({{ color_value }}); background-color: hsl({{ color_value }}/0.08); padding: 0 0.4em; border-radius: 0.4em;; line-height: 2.5em">
<span style="display: flex; flex-direction: row; align-items: center; margin-right: 0.4em; ">
{{ svg_code }}
{% if custom_type %}
<span style="">{{ custom_type }} |</span>
{% endif %}
</span>
{{ keywords }}
</span>
"""
# 创建 Jinja2 模板对象
tag_template = Template(tag_html_template)
card_template = Template(card_html_template)

""" 翻译参考
Learning material tags, learning material types, learning material type cards, custom learning material types, learning material keywords, associated_keyword learning materials. No association found 学习材料标记、学习材料的类型、学习材料类型卡、自定义的学习材料的类型、学习材料的关键词、关联的学习材料。未发现关联
""" # d、e、t、v、a类型段落标记替换成HTML代码
for match in matches:
# print(match)
# 段落标签内容
material_type, keywords, associated_keyword = match

# 段落卡片数据
material_card = card_template.render(
color_value=card_color[material_type],
svg_code=extract_modify_svg_content(icon_svg_filename[material_type], icon_svg_changes),
keywords=keywords.strip(),
)

# 关联段落卡片数据
if associated_keyword:
# 如果关联关键词存在
associated_types = find_associated_type(associated_keyword)
if associated_types:
# 找到关联段落
associated_type = associated_types[0]
associated_custom_type = associated_types[1]
associated_card = card_template.render(
color_value=card_color[associated_type],
svg_code=extract_modify_svg_content(icon_svg_filename[associated_type], icon_svg_changes),
custom_type=associated_custom_type,
keywords=associated_keyword
)
find_associated_svg = extract_modify_svg_content('Associated', icon_svg_changes)
else:
# 找到关联段落
associated_card = card_template.render(
color_value='0 0% 70%',
keywords=associated_keyword
)
find_associated_svg = extract_modify_svg_content('NotFoundAssociated', icon_svg_changes)
else:
# 如果没有关联关键词
associated_card = ''
find_associated_svg = ''

# 生成完整HTML代码
tag_html_code = tag_template.render(
material_card=material_card,
find_associated_svg=find_associated_svg,
associated_card=associated_card,
)

# print(tag_html_code)
# 找到对应文本并替换
new_markdown_text = new_markdown_text.replace(
f'\n{material_type}{keywords}{associated_keyword}\n', tag_html_code)

# c类型段落标记替换成HTML代码
for match_c in matches_c:
# print(match_c)
material_type, custom_type, keywords, associated_keyword = match_c

# 段落卡片数据
material_card = card_template.render(
color_value=card_color[material_type],
svg_code=extract_modify_svg_content(icon_svg_filename[material_type], icon_svg_changes),
custom_type=custom_type,
keywords=keywords.strip(),
)

# 关联段落卡片数据
if associated_keyword:
# 如果关联关键词存在
associated_types = find_associated_type(associated_keyword)
if associated_types:
# 找到关联段落
associated_type = associated_types[0]
associated_custom_type = associated_types[1]
associated_card = card_template.render(
color_value=card_color[associated_type],
svg_code=extract_modify_svg_content(icon_svg_filename[associated_type], icon_svg_changes),
custom_type=associated_custom_type,
keywords=associated_keyword
)
find_associated_svg = extract_modify_svg_content('Associated', icon_svg_changes)
else:
# 没有关联段落
associated_card = card_template.render(
color_value='0 0% 70%',
keywords=associated_keyword
)
find_associated_svg = extract_modify_svg_content('NotFoundAssociated', icon_svg_changes)
else:
# 如果没有关联关键词
associated_card = ''
find_associated_svg = ''

# 生成完整HTML代码
tag_html_code = tag_template.render(
material_card=material_card,
find_associated_svg=find_associated_svg,
associated_card=associated_card,
)
# print(tag_html_code)

# 找到对应文本并替换
new_markdown_text = new_markdown_text.replace(
f'\n{material_type}{custom_type}{keywords}{associated_keyword}\n', tag_html_code)

# print(new_markdown_text)

# 将生成的HTML代码发送给output_file,以UTF-8格式保存到新的Markdown文件中
with open(markdown_file, 'w', encoding='utf-8') as output_file:
output_file.write(new_markdown_text)


# 测试
convert_evoldown_to_markdown(r'markdown\example.md', r'markdown\example_output.md')
重绘SVG图形

为了方便自己对svg的处理和实现自己的显示风格的图标,所以重绘了官网的图标。

【尝试重绘渐构的段落图标】
https://www.modevol.com/document/clyqfgqgweaz61a3ybq3fm18

【第二次尝试重绘渐构的段落图标】
https://www.modevol.com/document/aakjqpiefnxddaqh661udjwr

[[尝试重绘渐构的段落图标]]
[[尝试重绘渐构的段落图标-存在的问题]]
[[第二次尝试重绘渐构的段落图标]]

声明 | 许可协议

by 刘鹏飞-冷瞳9I6 许可协议CC BY-NC-SA 4.0 Deed | 署名-非商业性使用-相同方式共享 4.0 国际 | Creative Commons