Hexo和Gitee一致,都是由Markdown文件为基础,构建的博客,编写Markdown本身无需多言,由于Hexo并非笔者的首选笔记管理方式,故而再其他地方构建和编写文件是常态,该Blog主要是利用其他工具来方便Hexo博文的编写(Header)
默认的是 hexo new [layout] title
可简写为 hexo n [layout] title
,其中布局应该是在博客目录中定义,该命令也局限于博客的对应目录。
post(默认)、draft、page
除了默认的方法,本篇将介绍Obsidian、VsCode-like、Vim自动添加Header的方式,用以方便随时随地的编写博文。
同时为了方便已有笔记迁移,本文也编写了Python脚本,CPY后为Target Dir的版本自动添加Header,但是其中对应的Catagories最好还是手动修改一下。
Obsidian 通过template 插件,按照对应主题的Header样式添加,可以去官方文档中找对应的语法和说明。从而构建自己的Template
Workflow :插件市场添加Template -> 设置指定Template文件夹 -> 按照语法编写Template文件 -> 使用快捷键插入模板
由于这一块没有什么存在歧义的操作,就不赘述,唯一需要注意的是语法,简单参考一下官方的Example 即可,无需过于深入
本文使用的是Live my Life的Hexo-Theme,模板文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ---title : <% tp.file .title %>catalog : true data : <% tp.date .now ("YYYY-MM-DD HH:mm:ss" ) %>subtitle :lang : cn header-img : /img/ header_img/lml_bg1.jpg tag : - categories : -mathjax : true sticky : 22 ---
实际上各个模块的操作思想都是一致的Snippet方案。
Vim/Nvim 通过Vimscript设置或者Lua的设置文件,令Vim,Neovim再新建.md
的同时,为其添加默认Header。Lua实际上调用的是Vimscript的接口,这里仅给出.lua
版本,相应的转换不在赘言。
配置NeoVim中的 ~/.config/nvim/lua/basic/config.lua
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 vim.cmd('autocmd BufNewFile *.md,*.sh,*.cpp,*.py,*.lua exec ":lua set_title()"' )function set_title () filetype = vim.fn.expand("%:e" ) if filetype == "md" then vim.fn.setline("1" , "--- " .. vim.fn.expand("%" )) vim.fn.append(vim.fn.line("." ), "" ) vim.fn.append(vim.fn.line("." )+1 , "Author: AikenHong " ) vim.fn.append(vim.fn.line("." )+2 , "Mail: h.aiken.970@gmail.com " ) vim.fn.append(vim.fn.line("." )+3 , "Date: " .. os .date ("%Y-%m-%d %H:%M:%S " )) vim.fn.append(vim.fn.line("." )+4 , "Desc: " )](<vim.fn.setline("1" , "---" ) vim.fn.append(vim.fn.line("." ), "title: " .. vim.fn.expand("%" )) vim.fn.append(vim.fn.line("." )+1 , "catalog: true" ) vim.fn.append(vim.fn.line("." )+2 , "subtitle: " ) vim.fn.append(vim.fn.line("." )+3 , "date: " .. os .date ("%Y-%m-%d %H:%M:%S " )) vim.fn.append(vim.fn.line("." )+4 , "lang: cn" ) vim.fn.append(vim.fn.line("." )+5 , "header-img: /img/header_img/lml_bg1.jpg" ) vim.fn.append(vim.fn.line("." )+6 , "tag: " ) vim.fn.append(vim.fn.line("." )+7 , "- " ) vim.fn.append(vim.fn.line("." )+8 , "categories: " ) vim.fn.append(vim.fn.line("." )+9 , "- " ) vim.fn.append(vim.fn.line("." )+10 , "mathjax: true" ) vim.fn.append(vim.fn.line("." )+11 , "sticky: " ) vim.fn.append(vim.fn.line("." )+12 , "" ) vim.fn.append(vim.fn.line("." )+13 , "---" )>) end end
这样当我们用nvim newblog.md
的时候,会自动添加上Header。
Vscode 使用Snippet插件添加代码片段,等待补充。
Convert md2Blogs 使用Python脚本为原有.md
批量添加Header,缺点是不太灵活,但是用于初始化还是能省不少事。如果原本按照Tag,或者Categories进行文件夹归类的话,倒是能起到不错的初始化效果。
Shut Out and Show my Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def get_all_blogs (path ): dirs = os.listdir(BlogPath) blogs = [] for blog_dir in dirs: if blog_dir not in ['.obsidian' ,'_book' , 'Day Planners' , 'node_module' ,'Draft' ]: tmpdir = os.path.join(BlogPath, blog_dir) blogs += glob.glob(tmpdir + '/*.md' ) for blog in blogs: if ' ' in blog: blog = blog.replace(' ' , '_' ) print (blog) return blogs
获取文件后我们需要得到文件的一些基本属性,用于Header中对应值的填充
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 def change_realtime (timestamp ): time_struct = time.localtime(timestamp) return time.strftime('%Y-%m-%d %H:%M:%S' , time_struct)def get_attribute (blog, verbose=False ): attr = {} create_time = os.path.getctime(blog) modify_time = os.path.getmtime(blog) attr['data' ] = change_realtime(create_time) attr['m_data' ] = change_realtime(modify_time) tags = blog.split('\\' )[-2 ] attr['tags' ] = tags attr['categories' ] = tags with open (blog, 'r' , encoding='UTF-8' ) as f: lines = f.readlines() title = lines[0 ].strip().split('#' )[1 ] attr['title' ] = title attr['lang' ] = 'cn' if verbose: print (blog, '\n' , attr) return attr
为了不意外损坏源文件,同时保持源文件的结构、组织和属性等等,我们Cpy并只对副本进行操作,cpy的同时转移文件路径到所需地点。
1 2 3 4 5 def cpy_files (blog,target ): """cpy files to the target path""" filename = os.path.basename(blog) os.system('cp ' + blog + ' ' + target + filename) return target + filename
在获取完基本属性和转移后,我们需要开始对文件进行添加header的处理,在这里我们添加了一个Loop为Blog设置不同的背景图片,根据自己有多少图片进行自定义设置吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def add_header (blog,index=0 ,attr=None ): """add default header for each files""" header_imgs = ["" ,1 , 2 , 3 , 4 ,5 ] with open (blog, "r+" , encoding='UTF-8' ) as f: old = f.read() f.seek(0 ) f.write("---\n" ) f.write("title: " + attr['title' ] + "\n" ) f.write("catalog: true\n" ) f.write("date: " + attr['data' ] + "\n" ) f.write("subtitle: \n" ) f.write("lang: " + attr['lang' ] + "\n" ) f.write("header-img: " + '/img/header_img/lml_bg{}.jpg' .format (index%6 ) + "\n" ) f.write("tags: " + "\n" ) f.write("- " + attr['tags' ] + "\n" ) f.write("categories: " + "\n" ) f.write("- " + attr['categories' ] + "\n" ) f.write("---\n" ) f.write(old) return
然后就是执行文件夹的批量处理了。可以添加args便于对多个文件夹进行处理,或者控制只变换单个文件等,应该需求不大,且代码比较简单,这里就暂时不贴出了。
1 2 3 4 5 6 7 8 9 10 def dir_process (): blogs = get_all_blogs(BlogPath) for i,blog in enumerate (blogs): b_attr = get_attribute(blog) new_blog = cpy_files(blog, TargetPath) add_header(new_blog, index=i, attr=b_attr)if __name__ == '__main__' : dir_process() print ('Done!' )