Coverage for src/jsoncrack_for_sphinx/generators/rst_generator.py: 96%

50 statements  

« prev     ^ index     » next       coverage.py v7.10.0, created at 2025-07-24 22:26 +0000

1""" 

2RST generation utilities for JSON schemas. 

3""" 

4 

5import json 

6from pathlib import Path 

7from typing import Any, Dict, Optional 

8 

9 

10def schema_to_rst(schema_path: Path, title: Optional[str] = None) -> str: 

11 """ 

12 Convert a JSON schema file to reStructuredText format. 

13 

14 This function is provided as a fixture for tests to convert schema 

15 files to reStructuredText format. 

16 

17 Args: 

18 schema_path: Path to the JSON schema file 

19 title: Optional title for the schema section 

20 

21 Returns: 

22 reStructuredText representation of the schema 

23 """ 

24 if not schema_path.exists(): 

25 raise FileNotFoundError(f"Schema file not found: {schema_path}") 

26 

27 try: 

28 # Read and validate JSON schema 

29 with open(schema_path, "r", encoding="utf-8") as f: 

30 schema_data = json.load(f) 

31 

32 # Create simple HTML representation of schema 

33 html_content = _generate_simple_schema_html(schema_data) 

34 

35 # Convert to RST 

36 rst_lines = [] 

37 

38 if title: 

39 rst_lines.extend( 

40 [ 

41 title, 

42 "=" * len(title), 

43 "", 

44 ] 

45 ) 

46 

47 rst_lines.extend( 

48 [ 

49 ".. raw:: html", 

50 "", 

51 ' <div class="json-schema-container">', 

52 f" {html_content}", 

53 " </div>", 

54 "", 

55 ] 

56 ) 

57 

58 return "\n".join(rst_lines) 

59 

60 except json.JSONDecodeError as e: 

61 raise ValueError(f"Invalid JSON in schema file {schema_path}: {e}") 

62 except Exception as e: 

63 raise RuntimeError(f"Error processing schema file {schema_path}: {e}") 

64 

65 

66def _generate_simple_schema_html(schema_data: Dict[str, Any]) -> str: 

67 """ 

68 Generate simple HTML representation of a JSON schema. 

69 

70 Args: 

71 schema_data: JSON schema data 

72 

73 Returns: 

74 HTML string representing the schema 

75 """ 

76 html_parts = [] 

77 

78 # Add title if present 

79 if "title" in schema_data: 

80 html_parts.append(f'<h3>{schema_data["title"]}</h3>') 

81 

82 # Add description if present 

83 if "description" in schema_data: 

84 html_parts.append(f'<p>{schema_data["description"]}</p>') 

85 

86 # Add basic schema info 

87 html_parts.append('<div class="schema-info">') 

88 

89 if "type" in schema_data: 

90 html_parts.append(f'<p><strong>Type:</strong> {schema_data["type"]}</p>') 

91 

92 # Add properties if it's an object schema 

93 if schema_data.get("type") == "object" and "properties" in schema_data: 

94 html_parts.append("<h4>Properties:</h4>") 

95 html_parts.append("<ul>") 

96 for prop_name, prop_info in schema_data["properties"].items(): 

97 prop_type = prop_info.get("type", "unknown") 

98 prop_desc = prop_info.get("description", "") 

99 is_required = prop_name in schema_data.get("required", []) 

100 required_text = " (required)" if is_required else "" 

101 

102 prop_line = ( 

103 f"<li><strong>{prop_name}</strong> " f"({prop_type}){required_text}" 

104 ) 

105 html_parts.append(prop_line) 

106 if prop_desc: 

107 html_parts.append(f"<br>{prop_desc}") 

108 html_parts.append("</li>") 

109 html_parts.append("</ul>") 

110 

111 # Add raw schema as collapsible section 

112 html_parts.append("<details>") 

113 html_parts.append("<summary>Raw Schema</summary>") 

114 html_parts.append("<pre>") 

115 html_parts.append(json.dumps(schema_data, indent=2)) 

116 html_parts.append("</pre>") 

117 html_parts.append("</details>") 

118 

119 html_parts.append("</div>") 

120 

121 return "\n".join(html_parts)