mistune-json 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ """
2
+ Mistune JSON Renderer.
3
+
4
+ A renderer for Mistune that outputs Markdown as JSON structures
5
+ instead of HTML.
6
+ """
7
+
8
+ from .json_renderer import JsonRenderer
9
+
10
+ __version__ = "0.1.0"
11
+ __all__ = ["JsonRenderer"]
@@ -0,0 +1,147 @@
1
+ from typing import Any, Dict, Iterable, List, Optional
2
+
3
+ import mistune
4
+
5
+
6
+ class JsonRenderer(mistune.HTMLRenderer):
7
+ """
8
+ A renderer for Mistune that outputs Markdown as JSON structures
9
+ instead of HTML.
10
+ """
11
+
12
+ def __init__(self, output: Optional[Dict[str, Any]] = None) -> None:
13
+ """
14
+ Initialize the JSON renderer.
15
+
16
+ Args:
17
+ output: Optional dictionary to update with rendered content
18
+ """
19
+ # No need for escape HTML or skip style in JSON renderer
20
+ super().__init__(escape=False, allow_harmful_protocols=False)
21
+ self._output: Dict[str, Any] = output if output is not None else {}
22
+
23
+ def render_tokens(self, tokens: Iterable[Dict[str, Any]], state: Any) -> List[Dict[str, Any]]:
24
+ """
25
+ Render a list of tokens into JSON structures.
26
+
27
+ Args:
28
+ tokens: Iterable of tokens to render
29
+ state: State object from Mistune parser
30
+
31
+ Returns:
32
+ List of rendered JSON structures
33
+ """
34
+ return list(self.iter_tokens(tokens, state))
35
+
36
+ def iter_tokens(self, tokens: Iterable[Dict[str, Any]], state: Any) -> Iterable[Dict[str, Any]]:
37
+ """
38
+ Iterate through tokens and yield rendered JSON structures.
39
+
40
+ Args:
41
+ tokens: Iterable of tokens to render
42
+ state: State object from Mistune parser
43
+
44
+ Yields:
45
+ Rendered JSON structures
46
+ """
47
+ for tok in tokens:
48
+ yield self.render_token(tok, state)
49
+
50
+ def __call__(self, tokens: Iterable[Dict[str, Any]], state: Any) -> Dict[str, Any]:
51
+ """
52
+ Main entry point for rendering.
53
+
54
+ Args:
55
+ tokens: Iterable of tokens to render
56
+ state: State object from Mistune parser
57
+
58
+ Returns:
59
+ Dictionary with rendered content
60
+ """
61
+ content = self.render_tokens(tokens, state)
62
+ # Filter out empty items
63
+ filtered_content = [item for item in content if item]
64
+ self._output.update({"content": filtered_content})
65
+ return self._output
66
+
67
+ # Block level tokens
68
+
69
+ def blank_line(self) -> Dict[str, Any]:
70
+ """Render a blank line."""
71
+ return {}
72
+
73
+ def paragraph(self, text: str) -> Dict[str, Any]:
74
+ """Render a paragraph."""
75
+ return {"type": "p", "content": text}
76
+
77
+ def heading(self, text: str, level: int) -> Dict[str, Any]:
78
+ """Render a heading."""
79
+ return {"type": "h", "content": text, "level": level}
80
+
81
+ def block_code(self, code: str, info: Optional[str] = None) -> Dict[str, Any]:
82
+ """Render a code block."""
83
+ result = {"type": "code", "content": code.strip()}
84
+ if info:
85
+ result["lang"] = info.strip()
86
+ return result
87
+
88
+ def block_quote(self, text: str) -> Dict[str, Any]:
89
+ """Render a block quote."""
90
+ return {"type": "blockquote", "content": text}
91
+
92
+ def list(self, text: str, ordered: bool, **attrs: int) -> Dict[str, Any]:
93
+ """Render an ordered or unordered list."""
94
+ if ordered:
95
+ result = {"type": "ol", "content": text}
96
+ start = attrs.get("start")
97
+ if start is not None:
98
+ result["start"] = start
99
+ return result
100
+ else:
101
+ return {"type": "ul", "content": text}
102
+
103
+ def list_item(self, text: str) -> Dict[str, Any]:
104
+ """Render a list item."""
105
+ return {"content": text}
106
+
107
+ def thematic_break(self) -> Dict[str, Any]:
108
+ """Render a thematic break (horizontal rule)."""
109
+ return {"type": "hr"}
110
+
111
+ # Span level tokens
112
+
113
+ def strong(self, text: str) -> Dict[str, Any]:
114
+ """Render strong emphasis."""
115
+ return {"type": "strong", "content": text}
116
+
117
+ def emphasis(self, text: str) -> Dict[str, Any]:
118
+ """Render emphasis."""
119
+ return {"type": "em", "content": text}
120
+
121
+ def codespan(self, text: str) -> Dict[str, Any]:
122
+ """Render inline code."""
123
+ return {"type": "codespan", "content": text}
124
+
125
+ def link(self, text: str, url: str, title: Optional[str] = None) -> Dict[str, Any]:
126
+ """Render a link."""
127
+ link = {"type": "a", "href": self.safe_url(url), "content": text}
128
+ if title:
129
+ link["title"] = title
130
+ return link
131
+
132
+ def image(self, text: str, url: str, title: Optional[str] = None) -> Dict[str, Any]:
133
+ """Render an image."""
134
+ return {
135
+ "type": "img",
136
+ "src": self.safe_url(url),
137
+ "alt": text,
138
+ **({"title": title} if title else {}),
139
+ }
140
+
141
+ def linebreak(self) -> Dict[str, Any]:
142
+ """Render a line break."""
143
+ return {"type": "br"}
144
+
145
+ def text(self, text: str) -> Dict[str, Any]:
146
+ """Render plain text."""
147
+ return {"type": "text", "content": text}
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.3
2
+ Name: mistune-json
3
+ Version: 0.1.0
4
+ Summary:
5
+ License: MIT
6
+ Author: fernandonino
7
+ Author-email: nino.fernando@gmail.com
8
+ Requires-Python: >=3.12
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: mistune (>=3.1.3,<4.0.0)
14
+ Description-Content-Type: text/markdown
15
+
16
+ # Mistune JSON
17
+ A JSON renderer for the [Mistune](https://github.com/lepture/mistune) Markdown parser.
18
+
19
+ ## Supported HTML elements
20
+ So far, the HTML elements supported by this renderer are limited to:
21
+
22
+ * Paragraph, `<p>`
23
+ * Image, `<img>`
24
+ * Ordered lists, `<ol>`
25
+ * Unordered lists, `<ul>`
26
+ * All heading elements, `<h1>` through `<h6>`
27
+ * Links, `<a>`
28
+ * Emphasis, `<em>`
29
+ * Strong, `<strong>`
30
+ * Blockquote, `<blockquote>`
31
+ * Line breake, `<br>`
32
+ * Thematic breake, `<hr>`
33
+ * Both inline and block code
34
+
35
+ ## How to use the JSON renderer
36
+ ### Installation
37
+ The package is not yet published in PyPI, but once it is, it will be installed with:
38
+ ```shell
39
+ pip install mistune-json
40
+ ```
41
+
42
+ ### Usage
43
+ ```python
44
+ import mistune
45
+ from mistune_json import JsonRenderer
46
+
47
+ # Create a renderer instance
48
+ renderer = JsonRenderer()
49
+
50
+ # Create a Markdown parser with the JSON renderer
51
+ markdown = mistune.create_markdown(renderer=renderer)
52
+
53
+ # Parse Markdown text
54
+ result = markdown("# Hello, world!")
55
+
56
+ print(result)
57
+ # {'content': [{'type': 'h', 'content': ['type': 'text', 'content': 'Hello, world!'], 'level': 1}]}
58
+ ```
59
+
60
+ ## Improvements and bugs
61
+
62
+ ### Tables
63
+ There is currently no support for rendering tables (headers and rows). It might be added in the future, if there is enough need for it. You can rise an issue [here](https://github.com/fernandonino/mistune-json/issues) and label it as _enhancement_.
64
+
65
+ ### Integration testing
66
+ Tests for a full Markdown document will be added to assure that the JSON render works as expected.
67
+
68
+ ### Bugs
69
+ If you find a problem with the JSON output structure, feel free to [report a bug](https://github.com/fernandonino/mistune-json/issues).
@@ -0,0 +1,5 @@
1
+ mistune_json/__init__.py,sha256=YhcKlkNUFuuq9Xf_-zGDK3XJ26RxGnVHXD5H1ZR61AI,204
2
+ mistune_json/json_renderer.py,sha256=xusj9_pqJMC_WymRSEQWdLajcgNjNqlcLyrHGi73HPs,4792
3
+ mistune_json-0.1.0.dist-info/METADATA,sha256=vChrWJhlv9kTZ2Pty8PwTVo1hdfJOfUyhHwtqCSeznA,2081
4
+ mistune_json-0.1.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
5
+ mistune_json-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.2
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any