Files
website/tools/content/jsonfile.py
T
2026-10-31 22:53:17 -04:00

71 lines
2.1 KiB
Python

import json
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
CONTENT_DIR = PROJECT_ROOT / "content"
INLINE_LIST_MAX_LENGTH = 80
INDENT = "\t"
def content_path(name: str) -> Path:
return CONTENT_DIR / name
def load(name: str):
with content_path(name).open(encoding="utf-8") as file:
return json.load(file)
def save(name: str, data) -> None:
text = format_value(data, 0) + "\n"
content_path(name).write_text(text, encoding="utf-8")
def is_primitive(value) -> bool:
return not isinstance(value, (dict, list))
def encode(value) -> str:
return json.dumps(value, ensure_ascii=False)
def format_inline_dict(data: dict) -> str:
if not data:
return "{}"
pairs = ", ".join(f"{encode(key)}: {format_value(value, 0)}" for key, value in data.items())
return "{ " + pairs + " }"
def format_inline_list(items: list) -> str:
return "[" + ", ".join(encode(item) for item in items) + "]"
def format_value(value, depth: int) -> str:
if isinstance(value, dict):
return format_dict(value, depth)
if isinstance(value, list):
return format_list(value, depth)
return encode(value)
def format_dict(data: dict, depth: int) -> str:
if depth > 0 and all(is_primitive(value) or is_short_primitive_list(value) for value in data.values()):
return format_inline_dict(data)
inner_indent = INDENT * (depth + 1)
lines = [f"{inner_indent}{encode(key)}: {format_value(value, depth + 1)}" for key, value in data.items()]
return "{\n" + ",\n".join(lines) + "\n" + INDENT * depth + "}"
def is_short_primitive_list(value) -> bool:
return isinstance(value, list) and all(is_primitive(item) for item in value) and len(format_inline_list(value)) <= INLINE_LIST_MAX_LENGTH
def format_list(items: list, depth: int) -> str:
if not items:
return "[]"
if is_short_primitive_list(items):
return format_inline_list(items)
inner_indent = INDENT * (depth + 1)
lines = [f"{inner_indent}{format_value(item, depth + 1)}" for item in items]
return "[\n" + ",\n".join(lines) + "\n" + INDENT * depth + "]"