Wave changes
This commit is contained in:
138
search-index.py
Executable file → Normal file
138
search-index.py
Executable file → Normal file
@@ -2,25 +2,72 @@ import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def get_org_id_and_title(file_path):
|
||||
"""Extract ID and TITLE from an Org file."""
|
||||
id_pattern = re.compile(r"^:ID:\s*(.+)", re.MULTILINE)
|
||||
title_pattern = re.compile(r"^#\+title:\s*(.+)", re.IGNORECASE | re.MULTILINE)
|
||||
# ================================
|
||||
# REGEX PATTERNS
|
||||
# ================================
|
||||
|
||||
ID_PATTERN = re.compile(r"^:ID:\s*(.+)", re.MULTILINE)
|
||||
TITLE_PATTERN = re.compile(r"^#\+title:\s*(.+)", re.IGNORECASE | re.MULTILINE)
|
||||
|
||||
# Org links:
|
||||
# [[id:...]]
|
||||
# [[file:...]]
|
||||
# [[./...]]
|
||||
LINK_PATTERN = re.compile(r"\[\[(.*?)\]\]")
|
||||
|
||||
|
||||
# ================================
|
||||
# PARSING FUNCTIONS
|
||||
# ================================
|
||||
|
||||
def parse_org_file(file_path):
|
||||
"""Extract ID, title, and links from an Org file."""
|
||||
content = file_path.read_text(encoding="utf-8", errors="ignore")
|
||||
|
||||
id_match = id_pattern.search(content)
|
||||
title_match = title_pattern.search(content)
|
||||
id_match = ID_PATTERN.search(content)
|
||||
title_match = TITLE_PATTERN.search(content)
|
||||
|
||||
org_id = id_match.group(1).strip() if id_match else None
|
||||
title = title_match.group(1).strip() if title_match else "Untitled"
|
||||
|
||||
return org_id, title
|
||||
links = extract_links(content)
|
||||
|
||||
return org_id, title, links
|
||||
|
||||
|
||||
def extract_links(content):
|
||||
"""Extract all internal Org links."""
|
||||
raw_links = LINK_PATTERN.findall(content)
|
||||
|
||||
links = []
|
||||
|
||||
for link in raw_links:
|
||||
# Remove description part: [[link][desc]]
|
||||
if "][" in link:
|
||||
link = link.split("][")[0]
|
||||
|
||||
# ID links
|
||||
if link.startswith("id:"):
|
||||
links.append(link.replace("id:", "").strip())
|
||||
|
||||
# File links
|
||||
elif link.startswith("file:"):
|
||||
path = link.replace("file:", "").strip()
|
||||
links.append(path)
|
||||
|
||||
# Relative links
|
||||
elif link.endswith(".org"):
|
||||
links.append(link.strip())
|
||||
|
||||
return links
|
||||
|
||||
|
||||
# ================================
|
||||
# MAIN GENERATOR
|
||||
# ================================
|
||||
|
||||
def generate_search_index(org_dir, out_file):
|
||||
"""Generate search-index.json with title, url, and id."""
|
||||
print("🔍 Generating search-index.json...")
|
||||
print("Generating search-index.json with links...")
|
||||
|
||||
org_dir = Path(org_dir).expanduser()
|
||||
out_file = Path(out_file).expanduser()
|
||||
@@ -30,51 +77,81 @@ def generate_search_index(org_dir, out_file):
|
||||
if not re.search(r"/\.#[^/]+\.org$", str(f))
|
||||
]
|
||||
|
||||
index = []
|
||||
# First pass: collect all files + IDs
|
||||
file_map = {} # id -> url
|
||||
path_map = {} # relative path -> url
|
||||
temp_entries = []
|
||||
|
||||
for file_path in org_files:
|
||||
org_id, title = get_org_id_and_title(file_path)
|
||||
filepath_relative = file_path.relative_to(org_dir).with_suffix('')
|
||||
|
||||
org_id, title, links = parse_org_file(file_path)
|
||||
relative = file_path.relative_to(org_dir).with_suffix('')
|
||||
url = f"/{relative}.html"
|
||||
|
||||
if org_id:
|
||||
index.append({
|
||||
"title": title,
|
||||
"url": f"/{filepath_relative}.html",
|
||||
"id": org_id
|
||||
})
|
||||
file_map[org_id] = url
|
||||
|
||||
path_map[str(relative) + ".org"] = url
|
||||
|
||||
temp_entries.append({
|
||||
"title": title,
|
||||
"url": url,
|
||||
"id": org_id,
|
||||
"raw_links": links
|
||||
})
|
||||
|
||||
# Second pass: resolve links → URLs
|
||||
index = []
|
||||
|
||||
for entry in temp_entries:
|
||||
resolved_links = []
|
||||
|
||||
for link in entry["raw_links"]:
|
||||
# ID link
|
||||
if link in file_map:
|
||||
resolved_links.append(file_map[link])
|
||||
|
||||
# File link
|
||||
elif link in path_map:
|
||||
resolved_links.append(path_map[link])
|
||||
|
||||
index.append({
|
||||
"title": entry["title"],
|
||||
"url": entry["url"],
|
||||
"id": entry["id"],
|
||||
"links": list(set(resolved_links)) # remove duplicates
|
||||
})
|
||||
|
||||
# De-duplicate by ID
|
||||
seen_ids = set()
|
||||
unique_index = []
|
||||
for entry in index:
|
||||
if entry["id"] not in seen_ids:
|
||||
if entry["id"] and entry["id"] not in seen_ids:
|
||||
unique_index.append(entry)
|
||||
seen_ids.add(entry["id"])
|
||||
|
||||
# Ensure output directory exists
|
||||
out_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Write JSON
|
||||
with open(out_file, "w", encoding="utf-8") as f:
|
||||
json.dump(unique_index, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"✅ search-index.json generated ({len(unique_index)} entries).")
|
||||
print(f"search-index.json generated ({len(unique_index)} entries).")
|
||||
|
||||
|
||||
# ================================
|
||||
# ALL FILES JSON (UNCHANGED)
|
||||
# ================================
|
||||
|
||||
def generate_all_files_json(search_index_file, out_file):
|
||||
"""Generate all-files.json from search-index.json."""
|
||||
search_index_file = Path(search_index_file).expanduser()
|
||||
out_file = Path(out_file).expanduser()
|
||||
|
||||
# Load data
|
||||
with open(search_index_file, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
print(f"🔎 Loaded {len(data)} entries from {search_index_file}")
|
||||
print(f"Loaded {len(data)} entries from {search_index_file}")
|
||||
|
||||
# Sort alphabetically
|
||||
data.sort(key=lambda x: x.get("title", "").lower())
|
||||
|
||||
# Group by first letter
|
||||
grouped = {}
|
||||
for entry in data:
|
||||
title = entry.get("title", "")
|
||||
@@ -87,7 +164,6 @@ def generate_all_files_json(search_index_file, out_file):
|
||||
"url": entry["url"]
|
||||
})
|
||||
|
||||
# Output structure
|
||||
output = {
|
||||
"title": "All Files",
|
||||
"description": "A complete alphabetical index of all published pages.",
|
||||
@@ -97,9 +173,13 @@ def generate_all_files_json(search_index_file, out_file):
|
||||
with open(out_file, "w", encoding="utf-8") as f:
|
||||
json.dump(output, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"✅ all-files.json generated → {out_file}")
|
||||
print(f"all-files.json generated → {out_file}")
|
||||
|
||||
|
||||
# ================================
|
||||
# ENTRY POINT
|
||||
# ================================
|
||||
|
||||
def main():
|
||||
base_dir = Path.home() / "master-folder" / "org_files" / "org_roam"
|
||||
search_index = base_dir / "output" / "search-index.json"
|
||||
|
||||
Reference in New Issue
Block a user