feat: Add template spell picker from spells.yml; polish spell table
All checks were successful
Deploy / deploy (push) Successful in 1m20s
All checks were successful
Deploy / deploy (push) Successful in 1m20s
- Add yaml-loader; import data/spells.yml at build time - Add SpellTemplate/SpellsFile types to globals.d.ts - Add 'Add Template Spell' button that opens a modal picker pre-filling all spell fields from the YAML data - Move spell data files into data/ directory - Split spell rows into inputs row + full-width notes row (colspan=6) - Shrink delete column to fit-content; bold spell name input - Add class column to spell table; change MP cost to free-text input - Auto-resize spell notes textarea on load and on input - Add 10px padding between spells for visual separation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
69
scripts/anchors.py
Normal file
69
scripts/anchors.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = [
|
||||
# "bs4",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# Dictionary to track how many times we've seen each header ID
|
||||
header_seen = {}
|
||||
|
||||
def add_anchors_to_headers(html_content):
|
||||
# Parse the HTML content
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
|
||||
# Find all header tags (h1 through h6)
|
||||
header_tags = soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])
|
||||
|
||||
# Add a count-based ID to each header tag
|
||||
for header in header_tags:
|
||||
# Extract header text (fallback to tag name if empty)
|
||||
header_text = header.get_text(strip=True) or header.name
|
||||
|
||||
# Normalize header
|
||||
header_text = header_text.lower().replace(" ", "-")
|
||||
|
||||
# Create base ID: hN-<text>
|
||||
base_id = f"{header.name}-{header_text}"
|
||||
|
||||
# Check if we've seen this base ID before
|
||||
if base_id in header_seen:
|
||||
# Append next count: -1, -2, -3...
|
||||
count = header_seen[base_id]
|
||||
header_seen[base_id] = count + 1
|
||||
header_id = f"{base_id}-{count + 1}"
|
||||
else:
|
||||
# First time seeing this text → count starts at 1
|
||||
header_seen[base_id] = 1
|
||||
header_id = base_id
|
||||
|
||||
# Add the ID to the header tag
|
||||
header['id'] = header_id
|
||||
|
||||
# Wrap the header in an anchor link (clickable permalink)
|
||||
# The link points to itself via the id attribute
|
||||
# anchor_tag = soup.new_tag("a", href=f"#{header_id}", class_="anchor-link")
|
||||
# anchor_tag.string = f"🔗"
|
||||
# header.wrap(anchor_tag)
|
||||
|
||||
# Return the modified HTML content
|
||||
return str(soup)
|
||||
|
||||
for book in ('./books/core', './books/natural-fantasy-atlas'):
|
||||
for root, dirs, files in Path(book).walk():
|
||||
for fn in files:
|
||||
path = root / fn
|
||||
if path.suffix != ".html":
|
||||
continue
|
||||
with path.open('r') as fh:
|
||||
raw_html = fh.read()
|
||||
|
||||
new_html = add_anchors_to_headers(raw_html)
|
||||
|
||||
with path.open('w') as fh:
|
||||
fh.write(new_html)
|
||||
Reference in New Issue
Block a user