feat: slim JSON, EmojiMarkupRenderer, configurable delimiters
- JSONRenderer(slim=True): null·기본값·빈 attributes 필드 제거 - EmojiMarkupRenderer: CTTree → 이모지 마크업 텍스트 왕복 변환 지원 - title_mark / section_marks 커스터마이징 가능 - names_per_line 옵션으로 줄당 이름 수 제한 - EmojiMarkupParser: 구분자를 생성자 파라미터로 주입 가능 - section_marks 길이 제한 없음 (임의 깊이 섹션 지원) - 긴 마커 우선 매칭으로 prefix 충돌 방지 - 테스트 39개 추가 (커스텀 구분자·렌더러·slim 검증) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,20 +6,53 @@ CTTree → JSON 렌더러
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
from ..tree import CTTree
|
||||
from .base import BaseRenderer
|
||||
|
||||
|
||||
class JSONRenderer(BaseRenderer):
|
||||
"""CTTree 를 JSON 문자열로 직렬화."""
|
||||
"""
|
||||
CTTree 를 JSON 문자열로 직렬화.
|
||||
|
||||
def __init__(self, indent: int = 2, ensure_ascii: bool = False) -> None:
|
||||
Args:
|
||||
indent: 들여쓰기 공백 수 (기본 2)
|
||||
ensure_ascii: ASCII 강제 인코딩 여부 (기본 False)
|
||||
slim: True 이면 null·기본값 필드를 제거해 출력을 간소화
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
indent: int = 2,
|
||||
ensure_ascii: bool = False,
|
||||
slim: bool = False,
|
||||
) -> None:
|
||||
self.indent = indent
|
||||
self.ensure_ascii = ensure_ascii
|
||||
self.slim = slim
|
||||
|
||||
def render(self, tree: CTTree) -> str:
|
||||
return json.dumps(
|
||||
tree.to_dict(),
|
||||
indent=self.indent,
|
||||
ensure_ascii=self.ensure_ascii,
|
||||
)
|
||||
data = tree.to_dict()
|
||||
if self.slim:
|
||||
data = self._strip(data)
|
||||
return json.dumps(data, indent=self.indent, ensure_ascii=self.ensure_ascii)
|
||||
|
||||
# ── slim 헬퍼 ─────────────────────────────────────────────
|
||||
|
||||
@staticmethod
|
||||
def _strip(obj: Any) -> Any:
|
||||
"""None·기본값 필드를 재귀적으로 제거."""
|
||||
if isinstance(obj, list):
|
||||
return [JSONRenderer._strip(v) for v in obj]
|
||||
if isinstance(obj, dict):
|
||||
result: dict[str, Any] = {}
|
||||
for k, v in obj.items():
|
||||
if v is None:
|
||||
continue
|
||||
if k == "data_type" and v == "unset":
|
||||
continue
|
||||
if k == "attributes" and v == {}:
|
||||
continue
|
||||
result[k] = JSONRenderer._strip(v)
|
||||
return result
|
||||
return obj
|
||||
|
||||
Reference in New Issue
Block a user