Hexo博客迁移Hugo方法

  1. Markdown文件的frontmatter不同,需要转换;
  2. 可能插入超链接、图片链接不同,需要转换;
  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
import yaml
import os
import glob
import re


def rename_key(dictionary, old_key, new_key):
    if old_key in dictionary:
        dictionary[new_key] = dictionary[old_key]
        del dictionary[old_key]

def delete_key(dictionary, old_key):
    if old_key in dictionary:
        del dictionary[old_key]


def check_and_increase_header_level(markdown_text):
    """
    检查Markdown文本中是否有1级标题,如果为true,增加标题的级别,同时要忽略代码块中的标题。
    """
    # Replace code blocks with placeholders
    code_block_regex = r"```.*?```"
    code_blocks = re.findall(code_block_regex, markdown_text, re.DOTALL)
    replaced_text = markdown_text
    placeholders = []
    for i, code_block in enumerate(code_blocks):
        placeholder = f"<CODEBLOCK{i}>"
        placeholders.append(placeholder)
        replaced_text = replaced_text.replace(code_block, placeholder)

    # Check if there are level-1 headers
    level_1_headers = re.findall(r"^# .*$", replaced_text, re.MULTILINE)
    if level_1_headers:
        # Increase the level of the headers
        headers_regex = r"^(#{1,6})(.*)$"
        replaced_text = re.sub(headers_regex, lambda match: "#" + match.group(1) + match.group(2), replaced_text, flags=re.MULTILINE)
    
    # Replace placeholders with the original code blocks
    for placeholder, code_block in zip(placeholders, code_blocks):
        replaced_text = replaced_text.replace(placeholder, code_block)
        
    return replaced_text


def read_markdown_with_frontmatter(md_file_path):
    """读取markdown文件"""
    with open(md_file_path, 'r', encoding='utf-8') as file:
        # Read the entire file content
        md_content = file.read()

        # Split Frontmatter and Markdown content
        frontmatter, md_text = md_content.split("---\n", 2)[1:]

        # Parse Frontmatter using yaml
        frontmatter_data = yaml.safe_load(frontmatter)

    return frontmatter_data, md_text



def write_markdown_with_frontmatter(md_file_path, frontmatter_data, md_text):
    """合并frontmatter与正文后写文件"""
    # 排序frontmatter
    new_frontmatter = ""
    fields_order = ["title", "date", "lastmod", "tags", "categories", "description",
                    "hidden", "image", "license", "math", "comments", "draft"]
    
    for field in fields_order:
        value = frontmatter_data.get(field)
        if value is not None:
            new_frontmatter += f"{field}: {value}\n"
        else:
            new_frontmatter += f"{field}: \n"
    
    md_text = check_and_increase_header_level(md_text)
    updated_md_content = f"---\n{new_frontmatter}---\n{md_text}"

    with open(md_file_path, 'w', encoding='utf-8') as file:
        # Write the updated content back to the file
        file.write(updated_md_content)


def work(md_file_path):
    frontmatter_data, md_content = read_markdown_with_frontmatter(md_file_path)
    rename_key(frontmatter_data,'updated','lastmod')
    delete_key(frontmatter_data,'keywords')
    delete_key(frontmatter_data,"top_img")
    delete_key(frontmatter_data,"highlight_shrink")
    delete_key(frontmatter_data,"cover")
    delete_key(frontmatter_data,"sticky")
    frontmatter_data["image"] = None
    frontmatter_data["math"] = False
    frontmatter_data["license"] = False
    frontmatter_data["hidden"] = False
    frontmatter_data["comments"] = False
    frontmatter_data["draft"] = False
    # frontmatter_data["tags"] = None
    # frontmatter_data["description"] = None
    # frontmatter_data["categories"] = None
    write_markdown_with_frontmatter(md_file_path, frontmatter_data, md_content)
if __name__ == "__main__":
    files = glob.glob(os.path.join('posts', "*.md"))
    for file in files:
        try:
            work(file)
        except:
            print(file)
  1. Stack:https://github.com/CaiJimmy/hugo-theme-stack

效果见:

如何优雅的从 Hexo 转移 Blog 到 Hugo

  1. HBS theme:https://hbs.razonyang.com/