Information Technology Grimoire

Version .0.0.1

IT Notes from various projects because I forget, and hopefully they help you too.

Hugo Create Site Structure Template

If you need to create a site skeleton quickly from a 2 column xlsx file, this script will do that for you. Modify the front matter template to your desired output. It should be run it’s own venv and then the resulting files copied to your hugo project.

It is designed to work specifically with the TechDoc Theme I’m using on this site and creates the automatic menus and front matter template for later editing with most parts filled out.

If you had 5 rows in an xlsx file, the first row being a header and the rows being something like:

MAIN,SUB, N/A,N/A
fruit, apple, N/A,N/A
fruit, peach, N/A,N/A
veg, spinash, N/A,N/A
veg, broc broc oii, N/A,N/A

It sould create a folder structure like the image with fruit and veg being main categories and the other items being sub categories, columns 3 and 4 are ignored in this script, but it can be modified to create affliate sites, shopping carts or XLSX driven starter doc templates too.

Requirements.txt

et-xmlfile==1.1.0
openpyxl==3.1.2
pytz==2023.3.post1

Create Main/Sub from XLSX

If you have an XLSX like the xample, this will create main and sub catetory skeleton structure for you.

import tkinter as tk
from tkinter import scrolledtext, filedialog
import os
import openpyxl
import pytz
from datetime import datetime, timezone

template_index_header = '''---
draft = false
author = "James Fraze"
description = ""
tags = ["", ""]
images = ["/i/x.png"]
'''

template_index_footer = '''---

{{ jameslist }}
'''
def load_file():
    global excel_data
    excel_data = []
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])
    if file_path:
        try:
            workbook = openpyxl.load_workbook(file_path)
            sheet = workbook.active
            for row in sheet.iter_rows(min_row=2):  # Assuming first row is header
                main_category = row[0].value
                sub_category = row[1].value if len(row) > 1 else None
                if main_category:
                    excel_data.append((main_category, sub_category))
                else:
                    output_text.insert("1.0", "Error: Some rows have missing data in the first column.\n")
                    return
            output_text.insert("1.0", "File loaded successfully. Ready to Hugofy!\n")
        except Exception as e:
            output_text.insert("1.0", f"Error reading file: {e}\n")

def normalize_string(s):
    return s.lower().replace(" ", "-")

def hugofy():
    output_text.delete("1.0", "end")
    hugo_dir = "hugo"
    os.makedirs(hugo_dir, exist_ok=True)  # Ensure the hugo directory exists

    created_main_folders = set()
    main_weight = 100
    for main_category, sub_category in excel_data:
        sub_weight = 100
        main_folder = normalize_string(main_category)
        main_folder_path = os.path.join(hugo_dir, main_folder)

        if main_folder not in created_main_folders:
            os.makedirs(main_folder_path, exist_ok=True)  # Create main folder path
            main_weight += 100
            created_main_folders.add(main_folder)
            output_text.insert(tk.END, f"Created main folder: {main_folder_path}\n")
            create_index_md(main_folder_path, main_category, main_category, main_folder, main_weight)

        if sub_category:
            sub_folder = normalize_string(sub_category)
            full_path = os.path.join(main_folder_path, sub_folder)
            os.makedirs(full_path, exist_ok=True)  # Create sub folder path
            sub_weight += 100
            output_text.insert(tk.END, f"Created sub folder: {full_path}\n")
            create_index_md(full_path, main_category, sub_category, sub_folder, sub_weight)

def create_index_md(folder_path, main_category, title, slug, weight):
    tz = pytz.timezone('America/Chicago')
    current_datetime = datetime.now(tz).isoformat(timespec='seconds')
    categories = [main_category.lower(), slug.lower()] if main_category != title else [main_category.lower()]
    print(slug,categories)

    # Adjust folder_path for the URL in front matter
    relative_path = folder_path.replace("hugo/", "")

    dynamic_header = f'''
url = "/{relative_path}"
categories = {categories}
slug = "{slug}"
title = "{title}"
date = "{current_datetime}"
lastmod = "{current_datetime}"
weight = {weight}
'''

    index_md_path = os.path.join(folder_path, "_index.md")
    if not os.path.exists(index_md_path):
        with open(index_md_path, 'w') as f:
            template_full = template_index_header + dynamic_header + template_index_footer
            f.write(template_full)
            output_text.insert(tk.END, f"Created file: {index_md_path}\n")


# Create the main window
root = tk.Tk()
root.title("Hugo Template Generator")
root.geometry("1200x400")

# Create a Grid layout
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(1, weight=8)  # 80% for output

# Create a Text widget for output
output_text = scrolledtext.ScrolledText(root, height=15, width=120)
output_text.grid(row=0, column=1, sticky='nsew', padx=5, pady=5)

# Create a Frame for buttons
button_frame = tk.Frame(root)
button_frame.grid(row=1, column=0, columnspan=2, pady=5)

# Create buttons
hugofy_button = tk.Button(button_frame, text="Hugofy", command=hugofy)
hugofy_button.pack(side=tk.LEFT, padx=5)

load_button = tk.Button(button_frame, text="Load", command=load_file)
load_button.pack(side=tk.LEFT, padx=5)

# Start the GUI event loop
root.mainloop()

Create Main from Text Input

If you have a site structure with only 1 level deep, this will create that structure in the order you specify.

import tkinter as tk
from tkinter import scrolledtext, filedialog
import os
import openpyxl
import pytz
from datetime import datetime, timezone

sample1 = '''Blues
Christmas
Civil War
Classical
Country
Disney
Folk
Grunge
Irish
Kids
Metal
Movies
Rock
Scales
Spanish
Video Game
Worship'''

sample2 = '''Overview
Training
Drills
SOP + Check Lists
Client Forms
Newsletters
Marketing
Meal Preps
Account Logins
Onboarding Staff
Billing
Funding
Construction
Contractors
Permits + Regulations
Insurance
Taxes
'''

template_index_header = '''---
draft = false
author = "James Fraze"
description = ""
tags = ["", ""]
weight = 1
images = ["/i/x.png"]
'''

template_index_footer = '''---

{{ jameslist }}
'''

def hugofy():
    output_text.delete("1.0", "end")
    hugo_dir = "hugo"
    os.makedirs(hugo_dir, exist_ok=True)  # Ensure the hugo directory exists
    created_main_folders = set()

    # Read data from input_text and process each line
    input_data = input_text.get("1.0", tk.END).strip().split('\n')
    weight = 100
    for line in input_data:
        # Assuming each line contains only the main category
        main_category = line.strip()
        if not main_category:
            continue  # Skip empty lines

        main_folder = normalize_string(main_category)
        main_folder_path = os.path.join(hugo_dir, main_folder)

        if main_folder not in created_main_folders:
            weight += 100
            created_main_folders.add(main_folder)
            output_text.insert(tk.END, f"Created main folder: {main_folder_path}\n")
            create_index_md(main_folder_path, main_category, main_category, main_folder, weight)


def normalize_string(s):
    return s.lower().replace(" ", "-")

def create_index_md(folder_path, main_category, title, slug, weight):
    tz = pytz.timezone('America/Chicago')  # CST Timezone
    current_datetime = datetime.now(tz).isoformat(timespec='seconds')
    categories = [main_category.lower(), slug.lower()] if main_category != title else [main_category.lower()]
    
    dynamic_header = f'''
url = "/{slug}"
categories = {categories}
slug = "{slug}"
title = "{title}"
date = "{current_datetime}"
lastmod = "{current_datetime}"
weight = {weight}
'''

    # Ensure the folder exists before creating the file
    os.makedirs(folder_path, exist_ok=True)

    index_md_path = os.path.join(folder_path, "_index.md")
    if not os.path.exists(index_md_path):
        with open(index_md_path, 'w') as f:
            template_full = template_index_header + dynamic_header + template_index_footer
            f.write(template_full)
            output_text.insert(tk.END, f"Created file: {index_md_path}\n")

def clear_texts():
    input_text.delete("1.0", "end")
    output_text.delete("1.0", "end")
            
def load_sample(sample):
    input_text.delete("1.0", "end")
    input_text.insert("1.0", sample)

# Create the main window
root = tk.Tk()
root.title("Hugo Template Generator")
root.geometry("1200x400")

# Create a Grid layout
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=2)  # 20% for input
root.grid_columnconfigure(1, weight=8)  # 80% for output

# Create a Text widget for input
input_text = scrolledtext.ScrolledText(root, height=15, width=30)
input_text.grid(row=0, column=0, sticky='nsew', padx=5, pady=5)

# Create a Text widget for output
output_text = scrolledtext.ScrolledText(root, height=15, width=120)
output_text.grid(row=0, column=1, sticky='nsew', padx=5, pady=5)

# Create a Frame for buttons
button_frame = tk.Frame(root)
button_frame.grid(row=1, column=0, columnspan=2, pady=5)

# Create buttons
hugofy_button = tk.Button(button_frame, text="Hugofy", command=hugofy)
hugofy_button.pack(side=tk.LEFT, padx=5)

# Create buttons for each sample
sample_button1 = tk.Button(button_frame, text="Load Sample 1", command=lambda: load_sample(sample1))
sample_button1.pack(side=tk.LEFT, padx=5)

sample_button2 = tk.Button(button_frame, text="Load Sample 2", command=lambda: load_sample(sample2))
sample_button2.pack(side=tk.LEFT, padx=5)

clear_button = tk.Button(button_frame, text="Clear", command=clear_texts)
clear_button.pack(side=tk.LEFT, padx=5)

# Start the GUI event loop
root.mainloop()