文章

创建jekyll插件以自动转换MP4附件链接

安心写作, 让插件替你解决视频附件不能展示的问题, 期待本插件能被官方收录

obsidian对于任何附件都是生成一条md链接指向附件文件夹, 而jekyll主题也默认不处理MP4 类型的附件链接, 导致插入视频时, 转换的网页不能正常显示. 于是我便借助千问大模型生成了一个jekyll-chirpy主题的插件, 用于在构建网页时, 自动处理MP4链接, 经测试, 该插件在本博客正常运行. 其他主题的博客请自行测试.

插件应位于

1
/_plugins/video_converter.rb

插件内容:

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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# Jekyll插件:Chirpy主题优化版MP4转视频标签插件

# 文件名:_plugins/video_converter.rb

  

module Jekyll

  # 使用Generator而不是Converter

  class VideoConverter < Generator

    safe true

    priority :high

  

    def generate(site)

      # 遍历所有页面和文章

      all_docs = site.pages + site.posts.docs + site.documents

      all_docs.each do |doc|

        next unless doc.content.respond_to?(:gsub)

        # 检查文档是否包含MP4相关内容

        if doc.content.match(/\.mp4/i)

          original_content = doc.content

          # 处理HTML中a标签包裹img标签的情况

          doc.content = doc.content.gsub(/(<a\s+[^>]*href=["']([^"']*\.mp4)["'][^>]*>\s*<img\s+[^>]*src=["']([^"']*\.mp4)["'][^>]*>\s*<\/a>)/mi) do |match|

            full_match = $1

            href_url = $2

            # 确保路径以/开头

            formatted_url = ensure_leading_slash(href_url)

            # 检查是否是本地文件

            if is_local_file?(href_url)

              %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签 </video>|

            else

              full_match

            end

          end

          # 处理单独的img标签指向MP4的情况

          doc.content = doc.content.gsub(/(<img\s+[^>]*src=["']([^"']*\.mp4)["'][^>]*>)/mi) do |match|

            full_match = $1

            img_src = $2

            # 确保路径以/开头

            formatted_url = ensure_leading_slash(img_src)

            if is_local_file?(img_src)

              %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签 </video>|

            else

              full_match

            end

          end

          # 处理Markdown风格的MP4链接

          doc.content = doc.content.gsub(/(!\[([^\]]*)\]\(([^)]*\.mp4(?:\?[^\s)]*)?)\))/mi) do |match|

            full_match = $1

            video_src = $3

            # 确保路径以/开头

            formatted_url = ensure_leading_slash(video_src)

            if is_local_file?(video_src)

              %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签 </video>|

            else

              full_match

            end

          end

          # 处理Obsidian风格的内部链接

          doc.content = doc.content.gsub(/(!\[\[(.*?\.mp4)(?:\|(.*?))?\]\])/mi) do |match|

            full_match = $1

            file_path = $2

            # 确保路径以/开头

            formatted_url = ensure_leading_slash(file_path)

            if is_local_file?(file_path)

              %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签 </video>|

            else

              full_match

            end

          end

          # 如果内容发生变化,记录一下

          if original_content != doc.content

            puts "VideoConverter: 转换了文档 #{doc.relative_path} 中的MP4链接"

          end

        end

      end

    end

  

    private

  

    def is_local_file?(path)

      path.start_with?('/') || path.start_with?('assets/') ||

      path.include?('images/') || path.include?('media/') ||

      path.include?('attachments/') || path.include?('posts/')

    end

    def ensure_leading_slash(path)

      return path if path.start_with?('/')

      "/#{path}"

    end

  end

  

  # 同时使用钩子在渲染后处理

  Hooks.register [:documents, :pages], :post_render do |doc, payload|

    # 只处理HTML输出

    if doc.output && doc.output.include?('.mp4')

      original_output = doc.output

      # 处理a标签包裹img标签的情况

      doc.output = doc.output.gsub(/(<a\s+[^>]*href=["']([^"']*\.mp4)["'][^>]*>\s*<img\s+[^>]*src=["']([^"']*\.mp4)["'][^>]*>\s*<\/a>)/mi) do |match|

        full_match = $1

        href_url = $2

        # 确保路径以/开头

        formatted_url = ensure_leading_slash(href_url)

        if is_local_file?(href_url)

          %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video>|

        else

          full_match

        end

      end

      # 处理单独的img标签指向MP4的情况

      doc.output = doc.output.gsub(/(<img\s+[^>]*src=["']([^"']*\.mp4)["'][^>]*>)/mi) do |match|

        full_match = $1

        img_src = $2

        # 确保路径以/开头

        formatted_url = ensure_leading_slash(img_src)

        if is_local_file?(img_src)

          %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video>|

        else

          full_match

        end

      end

      # 处理Markdown风格的MP4链接

      doc.output = doc.output.gsub(/(!\[([^\]]*)\]\(([^)]*\.mp4(?:\?[^\s)]*)?)\))/mi) do |match|

        full_match = $1

        video_src = $3

        # 确保路径以/开头

        formatted_url = ensure_leading_slash(video_src)

        if is_local_file?(video_src)

          %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video>|

        else

          full_match

        end

      end

      # 处理Obsidian风格的内部链接

      doc.output = doc.output.gsub(/(!\[\[(.*?\.mp4)(?:\|(.*?))?\]\])/mi) do |match|

        full_match = $1

        file_path = $2

        # 确保路径以/开头

        formatted_url = ensure_leading_slash(file_path)

        if is_local_file?(file_path)

          %Q|<video controls width="100%"> <source src="#{formatted_url}" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video>|

        else

          full_match

        end

      end

      # 如果内容发生变化,记录一下

      if original_output != doc.output

        puts "VideoConverter(post_render): 转换了 #{doc.id} 中的MP4链接"

      end

    end

    doc # 返回文档对象

  end

  

  def self.is_local_file?(path)

    path.start_with?('/') || path.start_with?('assets/') ||

    path.include?('images/') || path.include?('media/') ||

    path.include?('attachments/') || path.include?('posts/')

  end

  def self.ensure_leading_slash(path)

    return path if path.start_with?('/')

    "/#{path}"

  end

end
本文由作者按照 CC BY 4.0 进行授权