138 lines
3.7 KiB
Python
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()
|