Last active
January 16, 2026 05:37
-
-
Save ABB00717/5c589758b3284c021f966a857e15e5c5 to your computer and use it in GitHub Desktop.
A Python script that automatically generates and adds unique, short permalinks (e.g., /p/1a2b3c) to the YAML frontmatter of Markdown files, ensuring no duplicates across the project.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os | |
| import re | |
| import uuid | |
| TARGET_DIR = "content" | |
| FRONTMATTER_PATTERN = re.compile(r"^---\n(.*?)\n---", re.DOTALL) | |
| PERMALINK_PATTERN = re.compile(r"permalink:\s*(.+?)\s*$", re.MULTILINE) | |
| TEMPLATE_PATTERN = re.compile(r".*content/templates.*") | |
| def get_existing_permalinks(directory): | |
| """ | |
| Get all existing permalinks in all markdown files under a specific directory | |
| """ | |
| existing = set() | |
| for root, dirs, files in os.walk(directory): | |
| for file in files: | |
| if file.endswith(".md"): | |
| filepath = os.path.join(root, file) | |
| try: | |
| with open(filepath, "r", encoding="utf-8") as f: | |
| content = f.read() | |
| match = FRONTMATTER_PATTERN.match(content) | |
| if match: | |
| frontmatter = match.group(1) | |
| link_match = PERMALINK_PATTERN.search(frontmatter) | |
| if link_match: | |
| existing.add(link_match.group(1).strip()) | |
| except Exception as e: | |
| print(f"Reading Error {filepath}: {e}") | |
| return existing | |
| def generate_unique_permalink(existing_set): | |
| """ | |
| Generate a unique ID and ensure it doesn't collide with others | |
| """ | |
| while True: | |
| # Generate a 6-digit unique ID | |
| short_id = uuid.uuid4().hex[:6] | |
| candidate = f"/p/{short_id}" | |
| if candidate not in existing_set: | |
| existing_set.add(candidate) | |
| return candidate | |
| def process_file(filepath, existing_permalinks): | |
| try: | |
| with open(filepath, "r", encoding="utf-8") as f: | |
| content = f.read() | |
| except Exception as e: | |
| print(f"Couldn't read the file {filepath}: {e}") | |
| return | |
| match = FRONTMATTER_PATTERN.match(content) | |
| # If there's frontmatter in the file, we append a permalink to the existing one | |
| if match: | |
| frontmatter = match.group(1) | |
| # If there's already a permalink in the file | |
| if PERMALINK_PATTERN.search(frontmatter): | |
| return | |
| new_link = generate_unique_permalink(existing_permalinks) | |
| # Add a permalink to the frontmatter | |
| new_frontmatter = frontmatter.rstrip() + f"\npermalink: {new_link}\n" | |
| new_content = content.replace( | |
| f"---\n{frontmatter}\n---", f"---\n{new_frontmatter}---", 1 | |
| ) | |
| with open(filepath, "w", encoding="utf-8") as f: | |
| f.write(new_content) | |
| print(f"Added permalink [{new_link}]: {filepath}") | |
| else: | |
| # Otherwise, we generate a new one | |
| print(f"Creating a frontmatter for {filepath}") | |
| new_link = generate_unique_permalink(existing_permalinks) | |
| new_content = f"---\npermalink: {new_link}\n---\n\n" + content | |
| with open(filepath, "w", encoding="utf-8") as f: | |
| f.write(new_content) | |
| print(f"Added frontmatter and permalink [{new_link}]: {filepath}") | |
| def main(): | |
| if not os.path.exists(TARGET_DIR): | |
| print(f"Dir {TARGET_DIR} doesn't exist") | |
| return | |
| # Get all existing unique permalinks, ensuring we won't generate a duplicate | |
| # If we start gathering while in `process_file`, we might generate an ID and find out it has collided with an existing | |
| # permalink later, and we want to avoid that. | |
| existing_permalinks = get_existing_permalinks(TARGET_DIR) | |
| print(existing_permalinks) | |
| for root, dirs, files in os.walk(TARGET_DIR): | |
| for file in files: | |
| if file.endswith(".md") and not TEMPLATE_PATTERN.search(root): | |
| filepath = os.path.join(root, file) | |
| process_file(filepath, existing_permalinks) | |
| print("Done") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment