utility-app/scripts/build-excel-maps-from-old-a...

138 lines
3.7 KiB
Python

import json
import re
from pathlib import Path
OLD_APP = Path("/mnt/storage/sftp/mcelwain/repository/word-doc-generator")
OLD_CONSTANTS_CANDIDATES = [
OLD_APP / "public" / "constants.js",
OLD_APP / "constants.js",
]
OUT_DIR = Path("tools/doc_generator/content/excel_maps")
OUT_FILE = OUT_DIR / "legacy_excel_maps.json"
CELL_RE = re.compile(r"([A-Za-z_][A-Za-z0-9_]*)\s*:\s*['\"]([A-Z]{1,3}[0-9]{1,5})['\"]")
def find_constants_file():
for path in OLD_CONSTANTS_CANDIDATES:
if path.exists():
return path
raise SystemExit("Could not find old constants.js")
def extract_object_blocks(text):
"""
Finds JS object-ish assignment/export blocks that contain Excel cell mappings.
This is intentionally simple and robust for the old constants.js style.
"""
blocks = []
# Match things like:
# const fieldToCellMap = { ... };
# export const fieldToCellMap = { ... };
# let someMap = { ... };
pattern = re.compile(
r"(?:export\s+)?(?:const|let|var)\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*\{",
re.MULTILINE,
)
for match in pattern.finditer(text):
name = match.group(1)
start = match.end() - 1
depth = 0
end = None
for i in range(start, len(text)):
char = text[i]
if char == "{":
depth += 1
elif char == "}":
depth -= 1
if depth == 0:
end = i + 1
break
if end:
block = text[start:end]
cells = dict(CELL_RE.findall(block))
if cells:
blocks.append((name, cells))
return blocks
def label_from_name(name):
label = re.sub(r"([a-z])([A-Z])", r"\1 \2", name)
label = label.replace("_", " ").replace("-", " ")
label = re.sub(r"\s+", " ", label).strip()
return label.title()
def normalize_id(name):
value = re.sub(r"([a-z])([A-Z])", r"\1_\2", name)
value = re.sub(r"[^A-Za-z0-9]+", "_", value).strip("_").lower()
return value or "excel_map"
def discover_excel_templates():
templates = []
for path in sorted(OLD_APP.rglob("*.xlsx")):
if ".git" in path.parts or "node_modules" in path.parts:
continue
rel = path.relative_to(OLD_APP).as_posix()
templates.append({
"label": rel,
"legacyPath": str(path),
"filename": path.name
})
return templates
def main():
constants_path = find_constants_file()
text = constants_path.read_text(encoding="utf-8", errors="ignore")
blocks = extract_object_blocks(text)
excel_templates = discover_excel_templates()
maps = []
for name, cells in blocks:
map_id = normalize_id(name)
maps.append({
"id": map_id,
"sourceName": name,
"label": label_from_name(name),
"description": f"Generated from {constants_path.relative_to(OLD_APP)} object {name}.",
"template": excel_templates[0]["filename"] if excel_templates else "",
"legacyTemplateCandidates": excel_templates,
"fields": dict(sorted(cells.items(), key=lambda item: item[1]))
})
OUT_DIR.mkdir(parents=True, exist_ok=True)
OUT_FILE.write_text(json.dumps({
"id": "legacy_excel_maps",
"source": str(constants_path),
"maps": maps
}, indent=2), encoding="utf-8")
print(f"Wrote {OUT_FILE}")
print(f"Source: {constants_path}")
print(f"Excel templates found: {len(excel_templates)}")
for t in excel_templates:
print(f"- {t['legacyPath']}")
print(f"Maps found: {len(maps)}")
for item in maps:
print(f"- {item['id']}: {len(item['fields'])} fields")
if __name__ == "__main__":
main()