-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadd_redirects.py
More file actions
110 lines (93 loc) · 4.95 KB
/
add_redirects.py
File metadata and controls
110 lines (93 loc) · 4.95 KB
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
import os
import yaml
import argparse
from datetime import datetime
def load_config(site_dir):
"""Load the _config.yml file from the specified site directory."""
config_path = os.path.join(site_dir, "_config.yml")
with open(config_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
def generate_permalink(format_string, metadata, file_name):
"""Generate the permalink based on the format string and metadata."""
# Extract date from the file name (assuming YYYY-MM-DD-title.md format)
if "date" not in metadata:
date_str = file_name.split("-")[:3] # Extract YYYY-MM-DD
metadata["date"] = datetime.strptime("-".join(date_str), "%Y-%m-%d")
# Replace placeholders in the format string
permalink = format_string
if ":title" in permalink:
# Always use the title derived from the filename
title_from_filename = os.path.splitext(file_name)[0].split("-", 3)[-1]
metadata["title"] = title_from_filename # Overwrite metadata title with filename title
permalink = permalink.replace(":title", metadata["title"])
if ":year" in permalink:
permalink = permalink.replace(":year", str(metadata["date"].year))
if ":month" in permalink:
permalink = permalink.replace(":month", f"{metadata['date'].month:02d}")
if ":day" in permalink:
permalink = permalink.replace(":day", f"{metadata['date'].day:02d}")
if ":categories" in permalink:
categories = metadata.get("categories", "")
permalink = permalink.replace(":categories", categories)
# Ensure the permalink starts and ends with a slash
if not permalink.startswith("/"):
permalink = "/" + permalink
if not permalink.endswith("/"):
permalink += "/"
return permalink
def update_redirects(site_dir):
"""Update all posts with redirect_from based on the current permalink format."""
posts_dir = os.path.join(site_dir, "_posts")
config = load_config(site_dir)
permalink_format = config.get("permalink", "/:title/") # Default permalink format
for root, _, files in os.walk(posts_dir):
for file in files:
if file.endswith(".md") or file.endswith(".markdown"):
file_path = os.path.join(root, file)
with open(file_path, "r", encoding="utf-8") as f:
lines = f.readlines()
# Check if the file has front matter
if lines[0].strip() == "---":
# Extract front matter
end_index = lines[1:].index("---\n") + 1
front_matter_lines = lines[1:end_index]
content = lines[end_index + 1:]
# Parse front matter without altering its formatting
front_matter = yaml.safe_load("".join(front_matter_lines))
# Generate the current permalink
current_permalink = generate_permalink(permalink_format, front_matter, file)
# Add or update redirect_from in front matter
if "redirect_from" not in front_matter:
front_matter["redirect_from"] = []
if current_permalink not in front_matter["redirect_from"]:
front_matter["redirect_from"].append(current_permalink)
# Update the front matter lines with the new redirect_from value
redirect_from_yaml = yaml.dump(
{"redirect_from": front_matter["redirect_from"]},
default_flow_style=False
).strip()
updated_front_matter_lines = []
redirect_from_added = False
for line in front_matter_lines:
if line.startswith("redirect_from:"):
# Replace the existing redirect_from line
updated_front_matter_lines.append(redirect_from_yaml + "\n")
redirect_from_added = True
else:
updated_front_matter_lines.append(line)
if not redirect_from_added:
# Add redirect_from at the end of the front matter
updated_front_matter_lines.append(redirect_from_yaml + "\n")
# Write the updated file, preserving original front matter formatting
with open(file_path, "w", encoding="utf-8") as f:
f.write("---\n")
f.writelines(updated_front_matter_lines) # Write updated front matter lines
f.write("---\n")
f.writelines(content)
def main():
parser = argparse.ArgumentParser(description="Add redirect_from front matter to Jekyll posts.")
parser.add_argument("site_dir", help="Path to the Jekyll site directory")
args = parser.parse_args()
update_redirects(args.site_dir)
if __name__ == "__main__":
main()